请用C实现一个链表,实现链表的查找,逆置,替换,删除,添加,清空,创建。


查找、替换和删除、添加里面都会用到遍历链表的操作,所以重点在于遍历,

链表的逆置和清空考虑到效率,我们可以用递归实现,

至于创建节点,我们直接创建一个空节点作为头节点,不使用其数据域。


下面直接上代码:


#include <stdio.h>
#include <stdlib.h>

typedef struct stLIST
{
int data;
stLIST *next;
}LIST , *PLIST;

//链表的查找
PLIST ListFind(PLIST pHead, int data)
{
PLIST node = pHead;
while (node->next)
{
if (node->next->data == data)
{
return node->next;
}
node = node->next;
}
return NULL;
}

//链表的逆置
void ListReverse(PLIST pHead, PLIST pNode)
{
//用来存储新的尾部节点,在程序最后需要将尾部节点的next置为NULL
static PLIST HeadNext = NULL;
//如果链表没有节点,或者只有一个节点,则不予处理
if (pHead->next == NULL && pHead->next->next == NULL)
return ;
//如果是最后一个节点,我们将pHead的next指向它
//然后把最后节点的next指向他的前一个节点
if (pNode->next->next == NULL)
{
HeadNext = pHead->next;
pHead->next = pNode->next;
pNode->next->next = pNode;
return ;
}
//递归处理下一个节点
ListReverse(pHead, pNode->next);
//如果相等,则说明递归出来了,
//我们此时做收尾工作,将存储的静态新的尾部节点next置为NULL
if (pHead == pNode)
{
HeadNext->next = NULL;
return ;
}
//如果不等我们将此节点的下一节点指向自己
pNode->next->next = pNode;
return ;
}

//链表内容替换
void ListReplace(PLIST pHead, int data, int newData)
{
PLIST node = pHead;
while (node->next)
{
if (node->next->data == data)
{
node->next->data = newData;
}
node = node->next;
}
}

//删除指定数据的节点
void ListDel(PLIST pHead, int data)
{
PLIST node = pHead;
while (node->next)
{
if (node->next->data == data)
{
PLIST tempNode = node->next;
node->next = node->next->next;
free(tempNode);
return;
}
node = node->next;
}
}

//链表添加
bool ListAdd(PLIST pHead, int data)
{
//遍历到节点末尾
PLIST node = pHead;
while (node->next)
{
node = node->next;
}

node->next = (PLIST)malloc(sizeof(LIST));
if (NULL == node->next)
return false;

node->next->data = data;
node->next->next = NULL;

return true;
}

//链表清空
void ListDelAll(PLIST pHead)
{
if (pHead->next != NULL)
ListDelAll(pHead->next);

free(pHead->next);
pHead->next = NULL;
}

//链表创建
PLIST ListCreate()
{
PLIST pHead = (PLIST)malloc(sizeof(LIST));
pHead->data = 0;
pHead->next = NULL;

return pHead;
}

//链表打印,用于调试观察
void ListPrint(PLIST pHead)
{
PLIST node = pHead;
while (node->next)
{
printf("List data: %d \n", node->next->data);
node = node->next;
}
}

int main()
{
//创建链表
PLIST pHead = ListCreate();

//给链表添加内容
for (int i = 0; i < 10; i++)
{
ListAdd(pHead, i);
}

//清空链表
//ListDelAll(pHead);
//删除链表内容
ListDel(pHead, 6);
//逆置链表
ListReverse(pHead, pHead);

ListPrint(pHead);

return 0;
}


在实现以上代码中,主要在递归的逆置函数中花费时间比较多,

大家可以使用VS调试一遍更好的理解 逆置这个函数。

将光标移至函数头,然后按下F9,打一个断点,如下图所示:

基于Visual C++2013拆解世界五百强面试题--题7-链表的各种操作_#include


然后按F5启动调试:

基于Visual C++2013拆解世界五百强面试题--题7-链表的各种操作_递归_02

点按钮“是”进入调试,可以看到程序停在断点所在的位置了

基于Visual C++2013拆解世界五百强面试题--题7-链表的各种操作_链表_03


现在我们可以按F10单步调试,或者F11(可以跟进函数)。在调试窗口中看每一个变量的改变:

基于Visual C++2013拆解世界五百强面试题--题7-链表的各种操作_链表_04


如果有什么问题和疑问可以在下面留言互相探讨。

解压密码为 c.itcast.cn