看完这篇就明白了关于单链表的操作了

本文详细介绍了单链表的操作,包括单链表的读取、插入、删除节点的方法,强调了操作顺序的重要性。此外,还讨论了单链表与顺序存储结构在插入和删除操作上的效率差异,以及整表创建和删除的算法思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单链表的操作

双向链表、循环链表、静态链表请点击这里

1.单链表的读取

在线性表的顺序存储结构中,我们要计算任意一个元素的存储位置是很容易的。但在单链表中,由于第i个元素没办法一开始就知道,必须得从头开始找。

获得链表第 i 个数据的算法思路:

声明一个指针 p 指向链表第一个结点,初始化 j 从 1 开始;
当 j < i 时,就遍历链表,让 p 的指针向后移动,不断指向下一个结点,j 累加 1;
若到链表末尾 p 为空,则说明第 i 个结点不存在;
否则查找成功,返回结点 p 的数据。

实现代码算法如下:

/* 初始条件:顺序线性表 L 已经存在,1 <= i <= ListLength(L) */
/* 操作结果:用 e 返回 L 中第 i 个数据元素的值 */
Status GetElem(LinkList L, int i, ElemType *e)
{
   
	int j;
	LinkList p;		/* 声明一指针 p */
	p = L->next;	/* 让 p 指向链表 L 的第一个结点(有头结点的话就是指向头结点) */
	j = 1;			/* j 为计数器 */
	/* p 不为空且计数器 j 还没有等于 i 时,循环继续 */
	while (p && j < i)
	{
   
		p = p->next;	/* 让 p 指向下一个结点 */
		++j;
	}
	if (!p || j > i) 
		return ERROE	/* 第 i 个结点不存在 */
	*e = p->data;		/* 取第 i 个结点的数据 */
	return OK;
}

说白了,就是从头开始找,直到第 i 个结点为止。由于这个算法的时间复杂度取决于 i 的位置,当 i = 1 时,则不需遍历,当 i = n 时则遍历 n - 1 次才可以。因此最坏情况的时间复杂度是 O(n)。

由于单链表的结构中没有定义表长,所以不能事先知道要循环多少次,因此也就不方便使用for来控制循环。其主要核心思想就是“工作指针后移”,这其实也是很多算法的常用技术。

2.单链表的插入

假设存储元素 e 的结点为 s,要实现结点 p 、p->next 和 s之间逻辑关系的变化,只需将结点 s 插入到结点 p 和 p->next之间即可。如图:

在这里插入图片描述
可以发现,只需让 s->next 和 p->next 的指针做一点改变即可。

s->next = p->next;		/* 让p的后继结点改成s的后继结点 */
p->next = s;			/* 把结点s变成p的后继结点 */

三遍定律:

两句的顺序不可以交换!
两句的顺序不可以交换!
两句的顺序不可以交换!

那接下来我们看看为啥交换不得:
如果先p->next=s;再s->next=p->next;会怎么样?哈哈,因为此时第一句会使得将p->next给覆盖成s的地址了。那么s->next=p->next,其实就等于s->next=s。这样真正的拥有ai+1数据元素的结点就没了上级。这样的插入操作就是失败的,造成了临场掉链子的尴尬局面。

正确插入后是这样的。如图:

在这里插入图片描述
单链表第i个数据插入结点的算法思路:

1.声明一指针 p 指向链表头结点,初始化 j 从1 开始;
2.当 j < i 时,就遍历链表&#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值