单链表的头插法尾插法及删除节点操作

带头节点的单链表的头插法尾插法及删除节点操作

链表的操作对于初学者来说理解非常有难度,初学的同学们应该在学习链表的过程中多再练习本上画图,写一行代码就画出代码执行后链表各节点图的变化,方便理解。我也是刚学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;
	

图有点丑哈~

就这么多了,图画的有点丑哈~哈.

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

〖雪月清〗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值