刷LeedCode时使用单链表频出错误,于是花时间总结了一下单链表的基本操作,把所写代码和详细注释贴在这里,以备后用。
#include <stdio.h>
#include <stdlib.h>
/*定义结构体链表节点:
该结构体有两个属性,一个是int类型的数据域data,另一个是这个结构体本身类型的指针next;
最后给这个结构体定义了一个别名Node,一个指针别名pNode;
Node a; 就等价于struct NODE a; 都是声明一个struct NODE结构体类型的结构体变量a;
pNode p; 就等价于struct NODE* p; 等价于Node* p; 声明一个struct NODE结构体类型的指针变量p;*/
typedef struct NODE{
int data; //数据域
struct NODE* next; //指针域,指向下一个节点
}Node, *pNode;
//初始化一个链表节点
pNode init_node(int data)
{
pNode node = (Node*)malloc(sizeof(Node));
node->data = data;
node->next = NULL; //next为空
return node;
}
//遍历链表,打印输出每个节点的信息
void traverse_linkList(pNode phead)
{
pNode ptmp = phead;
while (ptmp)
{
printf("%d ", ptmp->data);
ptmp = ptmp->next;
}
printf("\n");
}
//头插法插入一个节点
pNode createLink_byHead(pNode phead, int data)
{
pNode pnode = init_node(data);//首先将准备插入的节点(数据)初始化为一个新的链表节点
if(NULL == phead)//如果插入前的链表为空,则返回当前的新节点
return pnode;
else{
pnode->next = phead;
return pnode;
}
}
//尾插法插入一个节点
pNode createLink_byTail(pNode phead, int data)
{
pNode pnode = init_node(data);//首先将准备插入的节点(数据)初始化为一个新的链表节点
pNode ptail =phead;//用于标记链表的尾节点,初始时为头结点
if(NULL == phead)
return pnode;//如果插入前的链表为空,则返回当前的新节点
else{
while (ptail->next)
{
ptail = ptail->next;
}//从头到尾遍历整个链表找到最后的尾节点
ptail->next = pnode;//将新的节点插入到最后
return phead;
}
}
//使用头插法或者尾插法建立一条单链表
pNode createSingleList(pNode phead)
{
int data, len;
pNode temp;
printf("请输入建立的链表节点个数:");
scanf("%d", &len);
for (int index = 0; index < len; index++)
{
printf("请输入第 %d 个节点的数值:", index + 1);
scanf("%d", &data);
//phead = createLink_byHead(phead, data);//使用头插法建立链表
phead = createLink_byTail(phead, data);//使用尾插法将建立链表
}
//打印输出链表中每一个节点
traverse_linkList(phead);
return phead;
}
//求链表的长度
int lengthofLinklist(pNode phead)
{
int len = 0;
pNode ptmp = phead;
while (ptmp)
{
len++;
ptmp = ptmp->next;
}
return len;
}
//按值查找(查找链表中等于某一数值的节点并返回,如果有多个则返回最前面的,如果没有则返回空)
pNode searchLinklist_byValue(pNode phead, int val)
{
pNode ptmp = phead;
if(NULL == phead)
return NULL;
while (ptmp)
{
if(ptmp->data == val)
return ptmp;
ptmp = ptmp->next;
}
return NULL;
}
//前插法(将新节点插入到与val值相等的第一个链表节点的前面)
pNode insertNode_fromPrev(pNode phead, int data, int val)
{
pNode pnew = init_node(data);//初始化新插入的节点
pNode ptmp = phead;
if(NULL == phead)//链表为空,直接返回新的节点
return pnew;
else if(phead->data == val){ //头节点是否为目标节点
pnew->next = phead;
return pnew;
}else{
while (NULL != ptmp->next && ptmp->next->data != val)
ptmp = ptmp->next;
if(NULL == ptmp->next)//没找到
{
printf("insert value not found\n");
}else{ //找到了,把新节点插入到目标节点的前面
pnew->next = ptmp->next;
ptmp->next = pnew;
}
}
return phead;
}
//后插法(将新节点插入到与val值相等的第一个链表节点的后面)
pNode insertNode_fromRear(pNode phead, int data, int val)
{
pNode pnew = init_node(data);//初始化新插入的节点
if(NULL == phead)//链表为空,直接返回新的节点
return pnew;
pNode ptmp = searchLinklist_byValue(phead, val);//调用按值查找函数
if (NULL == ptmp)//没有找到
printf("insert value not found\n");
if(NULL == ptmp->next)//如果目标节点为最后一个节点
ptmp->next = pnew;
else{ //将新节点插入到目标节点后面
pnew->next = ptmp->next;
ptmp->next = pnew;
}
return phead;
}
//删除节点(删除链表中所有等于val的节点)
pNode deleteNode(pNode phead, int val)
{
pNode ptmp = phead;
pNode pdel = NULL;
if(NULL == phead)//链表为空
{
printf("Linklist is empty,delete fail!\n");
return phead;
}else if(phead->data == val)//删除头结点
{
phead = phead->next;
free(ptmp);
ptmp = NULL;
}else{
while (NULL != ptmp->next && ptmp->next->data != val)
{
ptmp = ptmp->next;
}
if(NULL == ptmp->next)//找不到
{
printf("delete value is not found, delete fail!\n");
}else if(ptmp->next->data == val){ //找到目标点(包括删除的节点是尾节点的情况)
pdel = ptmp->next;
ptmp->next = pdel->next;
free(pdel);
pdel = NULL;
}
}
return phead;
}
int main()
{
pNode phead, p;
phead = NULL;
phead = createSingleList(phead);//从无到有建立一条单链表,返回的phead是这条链表的头指针
int len = lengthofLinklist(phead);
printf("链表的长度为:%d\n", len);
//phead = insertNode_fromPrev(phead, 100, 10);
//phead = insertNode_fromRear(phead, 100, 10);
phead = deleteNode(phead, 100);
traverse_linkList(phead);
system("pause");
return 0;
}
来源:CSDN
作者:MagnumLu
链接:https://blog.csdn.net/qq_28584889/article/details/83550172