带头节点的单链表的头插法尾插法及删除节点操作
链表的操作对于初学者来说理解非常有难度,初学的同学们应该在学习链表的过程中多再练习本上画图,写一行代码就画出代码执行后链表各节点图的变化,方便理解。我也是刚学c语言不久,也是第一次写博客,如果有什么不对的地方,还望 大家多~多指教。
首先先看一下单个节点的结构:
typedef struct node{
int data; //数据域
struct node*next; //指针域
}Node;
(注意我用 typedef 将struct node 重新命名为Node,如果没有这个重命名所有Node 的地方全部要改为struct node.)
首先:注意区分头节点和头指针,头节点可有可无,头节点的存在是为了方便单链表的操作,本质是一个节点,它的数据域无意义一般存 0. 而头指针是必须要存在的,本质是一个指针.
然后 :如果头节点存在,头指针就指向头节点,若头节点不存在,头指针就指向链表中第一个节点.
1.创建一个带头节点的单链表:
Node*create() //创建链表带头节点
{
Node*head=NULL;
head=(Node*)malloc(sizeof(Node));
if(NULL==head)
{
printf("memory out of use\n"); //内存分配不足,一般不会出现
return NULL;
}
head->data=0;
head->next=NULL;
return head;
}
2.头插法增加节点:(自动忽视函数名 哈~)
int hhh(Node*head,int num) //头插法增加链表节点 num为插入新节点的数据
{
Node*p=head->next,*pr=NULL; //pr为新节点并初始化
pr=(Node*)malloc(sizeof(Node));
if(NULL==pr)
{
printf("memory out of use\n");
return NULL;
}
pr->data=num;
pr->next=p;
head->next=pr;
return 0;
}
3.尾插法增加新节点:(自动忽视函数名 哈~)
int hh(Node*head,int num) //尾插法增加链表节点
{
Node*p=head,*pr=NULL; //pr为新节点并初始化
pr=(Node*)malloc(sizeof(Node));
if(NULL==pr)
{
printf("memory out of use\n");
return NULL;
}
pr->data=num;
if(NULL==head->next) //判断是否为空链表
{ // 若为空链表 则将新的节点插在头节点后
head->next=pr;
pr->next=NULL;
}
else { //若不是空链表,则遍历链表找到最后的节点 p
while(p->next!=NULL)
{
p=p->next;
}
p->next=pr; //插入新的节点
pr->next=NULL;
}
}
3.打印链表:
void display(Node*head) //打印链表
{
Node*pr=head->next;
while(pr){
printf("%d ",pr->data);
pr=pr->next;
}
}
4.删除指定数据的节点:
int del(Node*head,int num) //按值查找删除节点
{
Node*p=head,*pr=NULL;
if(NULL==head) //如果链表为空
{
printf("empty list\n");
return -1;
}
while(p->next->data!=num) //遍历单链表找到要删除节点的前一个节点
{
p=p->next;
}
if(NULL==p) //如果没有找到
{
printf("no find the node\n");
return -1;
}
pr=p->next; //pr为临时指针指向要删除的节点 保证下一步删除时后面的链表能够知道
p->next=p->next->next; //要删除节点的前一个节点指向后一个节点
free(pr); // 释放 pr
return 0;
}
5.主函数:
int main()
{
Node*head=create();
for(int i=1;i<=3;i++) //头插法单链表赋数据值 亦可以自己循环输入
{
hhh(head,i);
}
del(head,2); //删除指定值的节点,值可以自己控制
display(head); //打印头插法建立的单链表
printf("\n");
for(int i=1;i<=3;i++) //尾插法单链表赋数据值 亦可以自己循环输入
{
hh(head,i);
}
del(head,2); //删除指定值的节点,值可以自己控制
display(head); //打印尾插法建立的单链表
return 0;
}
注意我只建立了一条单链表,为了能一次展示出来把代码都放在一起了,但是这样运行第二次单链表的操作的前提肯定包含了前一次操作的结果,大家写的时候要分开,或者直接建立两个单链表。
补充两节点的交换(只有关键交换的代码......)
pr->next=p->next;
p->next=pr->next->next;
pr->next->next=p; //注意顺序
p=p->next; //后移
pr=pr->next;
就这么多了,图画的有点丑哈~哈.