链表 [2] —— 静态链表中指点节点的后方以及前方插入新节点

文章转载请注明出处,加上原文地址链接,谢谢!https://blog.csdn.net/weixin_46959681/article/details/110672699



当前节点的判断

不论是在指定节点的后方或者前方插入新节点,我们第一步要做的是对当前节点做出判断,判断链表中的当前节点是否是我们所指定要插入新节点的节点。


如何在指定节点后方进行插入新节点?

以第三点节为指定节点,我们对指定节点、新节点以及节点之间的连接(主要通过指针实现)做出相应操作,具体有以下两个步骤:

  1. 以节点为对象元素,对彼此之间的函数对应关系做出修改(即修改指针的指向)。对应笔者所列的图片可以清楚的看到,第一步将链表中的第三节点和第四季节点的函数关系(即通过指针操作进行指向)赋值给新节点,让其指向第四个节点。笔者在此处用了比较数学化的说法,代码实现为 new->next = 3->next
  2. 第一步的基础之上,通过指针操作改变第三节点原来的指向,使第三节点和新节点之间建立指向关系。
    代码实现为 3.next = new在这里插入图片描述

代码演示:

int insertFromBehind(struct Test *head, int data, struct Test *new)
{
	//保持链表头部不动,使用指针point进行位移。
	struct Test *point;
	point = head;
	//指针不指向野指针表明指针point指向链表当中的某一节点。 
	while(point != NULL) 
	{
		if(point->data == data) //data为指定节点内的数据。
		{
				new->next = point->next; 
				point->next = new;
		}
		//该处的指针位移表示指针point访问到的数据与指定插入节点数不匹配,所以会位移继续匹配数据。
		point = point->next; 
	}
}

如何在指定节点前方插入新节点?

对于在指定节点前方插入新节点的实现肯定与在后方插入完全不同。就在指定节点前方插入而言,可以分为两种不同的情形:

  1. 在链表头插入;(些许博文有使用到二级指针。)
  2. 在链表中某一个指定节点前方插入。

下面我们针对两种情况以画图的方式展开分析。

|在链表头部插入

在展开链表头部插入之前,我们必须有一个问题要解决。链表的第一个节点已经是链表头。在实现头部插入新节点时,势必会对链表头的地址进行相应的操作,这就要求我们必须创建一个含有地址变量的变量。此时的链表头 head 已经包含了第一个节点的地址为 一 级 指 针 \color{red}一级指针 ,故此变量必须要包含链表头 head 这个一级指针的地址,即所谓 二 级 指 针 \color{red}二级指针 笔者不打算使用二级指针,但是所用代码产生的效果是一样的。

图中的指针 head 和指针 point 都指向链表中第一个节点,head 用于固定链表头, point 用于指针的位移实现其他辅助操作,并且 point永远指向当前节点。

头插法
如何实现链表头前方插入呢?思路大致如下:

  • 检查当前节点的数据和头部节点的数据是否一致,即 point->data == data;
  • 在数据匹配一致的基础上,将新节点的指针指向链表头, 即 new->next = head

片段代码演示:

struct Test *point;
point = head;
//判断当前节点的数据是否和链表头节点的数据匹配。
if(point->data == data)
{
	//将新节点的指针指向链表头。
	new->next = head; 
	//返回并使新节点成为头节点。
	return new; 
}

|在链表的其他指定节点前方插入

如何实现链表的其他节点前方插入新节点呢?大致思路如下:

  • 保证指针在位移时永远非空,表明指针在链表的范围内进行活动,即 point->next != NULL;
  • 判断当前节点的数据是否和指定节点的数据相匹配,即 if(point->next->data == data)
  • 在上一步成立的情况下,将新节点指向当前节点的下一个节点,即 new->next = point->next。之后,将当前节点指向新节点,即 point->next =new

在这里插入图片描述

代码演示:

//保证当前节点的下一个节点非空。
while(point->next != NULL)
{
	//使用函数 printf() 追踪节点数据的流向非常重要!非常重要!
	printf("data = %d, point = %d\n", point ->next->data, data); 
	//节点数据进行匹配。
	if(point->next->data == data) 
	{
			//新节点与下一个节点建立指向关联。
			new->next = point->next; 
			point->next = new; 
			printf("insert success.\n");
			return point;
	}
	point = point->next;
}
//超过链表范围,匹配数据失败。
printf("链表中没有节点包含这个数据 %d。\n", data); 
return point;

提示:在演示代码敲完之后,整篇文章笔者从前往后仔细看了一遍,产生一个自己迷惑自己的乌龙。那就是指针 point 是指向当前节点,而形式参数 data 是指定的节点里的数据。两者千万不要混为一谈。🤣


两段代码合并放在一个窗口下

int insertFromBehind(struct Test *head, int data, struct Test *new)
{
	struct Test *point;
	//保持链表头部不动,使用指针point进行位移。
	point = head; 
	//指针不指向野指针表明指针point指向链表当中的某一节点。
	while(point != NULL) 
	{
		//data为指定节点内的数据。
		if(point->data == data) 
		{
				new->next = point->next; 
				point->next = new;
		}
		//该处的指针位移表示指针point访问到的数据与指定插入节点数不匹配,所以会位移继续匹配数据。
		point = point->next; 
	}
}


struct Test *insertFromfor(int insertFromBehind(struct Test *head, int data, struct Test *new))
{
	struct Test *point;
	point = head;
	//判断当前节点的数据是否和链表头节点的数据匹配。
	if(point->data == data) 
	{
		//将新节点的指针指向链表头。
		new->next = head; 
		//返回并使新节点成为头节点。
		return new; 
	}	
	while(point->next != NULL)
	{
			//使用函数 printf() 追踪节点数据的流向非常重要。
			printf("data = %d, point = %d\n", point ->next->data, data);
				 
			if(point->next->data == data)
			{
					//新节点与下一个节点建立指向关联。
					new->next = point->next; 
					point->next = new; 
					printf("insert success.\n");
					return point;
			}
			point = point->next;
	}
	//超过链表范围,匹配数据失败。
	printf("链表中没有节点包含这个数据 %d。\n", data); 
	return point;
}


思索

在写文章的时候笔者渐渐有股莫名的感觉,就真实的项目代码而言肯定和笔者所敲的代码有些许差别。就以指定节点的形式参数而言,笔者不知道是不是直接以变量名 data 的形式传递,又或者用到了指针的方式。毕竟笔者只是初学者,企业里真实的项目根本没有实践过。

另外,关于主函数 main 的部分就不在多做演示了,合并添加下来展示,整片博文就过于庞大了。


文章更新记录

  • 文章初步完成。「2020.12.5 21:47」
  • 修改部分文字的表述。「2020.12.8 10:18」
  • 一篇比较详细的C语言链表博文,没有用到二级指针。c语言链表详解(超详细)「2020.12.11 21:05」
  • 修改了演示中错误的代码。 「2021.1.9 15:02」
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值