手把手教你:单链表的创建,以及各种插法、删法(基于C语言)(其二)

文章详细介绍了链表的头插法,即在头节点后插入新节点,以及如何实现指定位置插入节点。对于位置插入,文章考虑了位置为0时相当于头插,位置大于实际节点数时采用尾插的情况。此外,还讲解了在指定数据后面插入新节点的方法。
摘要由CSDN通过智能技术生成

书接上回

其一中,我们讲解了单链表的设计、创建、以及尾插法,这回我们讲解链表的头插法,指定位置插入法,指定数据后面插入法

链表的头插法:

链表的头插法,即在头节点的后面、首元节点的前面插入节点(分不清头节点和首元节点的可以去百度搜一下)。通俗点说就像是插队一样。

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

void push_head(List* list, int data)
{
	Node* newNode = createNode(data);
	newNode->next = list->next;
	list->next = newNode;
}

我们继续分步骤来为大家讲解:

  1. 和尾插法一样,push_head函数的参数,指定了我们要插入到哪个链表以及要插入什么数据
  2. 同样调用createNode创建需要插入的节点。
  3. 有人看到newNode->next = list->next 就懵逼了,前面介绍的时候说到,头插法是在头节点的后面、首元节点的前面插入节点,因此,newNode->next = list->next,代表了新的节点指向原来的首元节点,因为list->next其实就代表了首元节点了嘛。
  4. 而list->next = newNode,代表了头节点重定向 指向了新插入的节点。至此,头插法就完成了,如若依旧看不懂的话,建议手工画图,来模拟头插法的过程。

链表的指定位置插入法:

虽然链表并不像数组那样,存在索引,但是没有索引不妨碍我们抽象出一个索引出来

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

void push_pos(List* list, int position, int data)
{
	Node* curNode = list;
	Node* newNode = createNode(data);
	int location = 0;	    //用于抽象位置
	while (curNode->next)
	{
		if (position == location++)
		{
			newNode->next = curNode->next;
			curNode->next = newNode;
			break;
		}
		curNode = curNode->next;
	}
	if (location == 0)
	{
		push_head(list, data);
	}
	if (position > location)
	{
		push_back(list, data);
	}
}

但是由于指定位置插入法需要一些特殊情况,因此代码会复杂一些

需要考虑的情况有一下:

  • 假如position为0,这个时候就相当于是头插了
  • 链表并没有那么长,position参数给出的位置却比链表的节点数还要大

所以我们需要针对上述情况进行相应的调整。

我们依旧逐一解释:

  1. 我们先设置抽象出索引int location = 0来表示当前所在的位置(索引从0开始)
  2. 我们用while循环去遍历链表,curNode表示当前遍历到的节点
  3. 在循环体中,我们每次循环都进行 if 判断,如果position == location++,这里不仅起到了判断作用,而且先判断,再location自增,只要判断成立了,就用 if 中的代码进行插入操作,并且break退出循环
  4. if(location == 0),即为我们需要考虑的第一个情况:position的的值为0,那么这时候就相当于在 0 号位插入节点,所以我们果断调用先前写好的头插函数,就不用繁琐的复制粘贴了
  5. if(position > location),即为我们需要考虑的第二个情况:position参数比链表的节点数还要大。那么这个时候捏,我选择的解决方法就是直接用尾插,因此反正position的值没有意义,与其输出错误警告,不如直接在尾部插入节点。

在指定数据后面插入数据:

在指定数据后面插入数据也是比较简单的一种插法

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

void push_after(List* list, int after, int data)
{
	Node* newNode = createNode(data);
	Node* curNode = list;
	while (curNode->next)
	{
		if (curNode->data == after)
		{
			newNode->next = curNode->next;
			curNode->next = newNode;
			break;
		}
		curNode = curNode->next;
	}
}

鉴于与之前的有雷同,所以长话短说。这里我们遍历整个链表,当if (curNode->data == after)满足条件时,代表我们找到了需要的数据,然后在插入后,break退出循环即可。

鉴于篇幅原因,链表的各种删法,会在其三当中进行讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值