Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >数据结构——lesson3单链表介绍及实现

数据结构——lesson3单链表介绍及实现

作者头像
大耳朵土土垚
发布于 2024-03-13 10:44:12
发布于 2024-03-13 10:44:12
14200
代码可运行
举报
文章被收录于专栏:c/c++c/c++
运行总次数:0
代码可运行

1.什么是链表?

链表是一种 物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序是通过链表中的 指针链 次序实现的 。

逻辑图如下:

可以看出链表有两个变量,一个存放数据,另一个存放指向下一节点的指针;

此外链表还具有以下特征:

(1)链表在逻辑上连续,但在物理上不一定连续;

(2)链表的节点在现实中一般都是在堆上开辟出来的,所以使用结束后需要释放空间;

(3)从堆上申请的空间是按照一定策略分配的,所以物理空间可能连续也可能不连续。

2.链表的分类

链表按单向双向、无头带头、循环非循环可分为多种,这里我们介绍最常用的两种——无头单向非循环链表、带头双向循环链表。本篇文章将详细介绍无头单向非循环链表(简称单链表)的增删查改等的实现。

(1)无头单向非循环链表:

结构简单,一般不会单独用来存数据。实际中更多是作为 其他数据结构的子结 ,如哈希桶、图的邻接表等等。另外这种结构在 笔试面试中出现很多。

(2)带头双向循环链表:

结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

3.单链表的实现

(1)单链表的定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;//存放数据
	struct SListNode* next;//存放下一个节点的指针
}SListNode;

结构体定义两个变量,一个是SLDataType类型的数据,另一个时结构体的指针用来存放下一节点指针;

(2)动态创建节点

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//申请新的节点,返回指向节点的指针
SListNode* BuySListNode(SLTDateType x)
{
	SListNode* buynode = (SListNode*)malloc(sizeof(SListNode));
	buynode->data = x;
	buynode->next = NULL;
	return buynode;
}

(3)单链表打印

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表打印
void SListPrint(SListNode* plist)
{
	//assert(plist);//没有节点,指针为空,断言,为空也可打印空指针所以不需要断言
	SListNode* psl = plist;//用一个临时变量接收,如果不喜欢也可以不用
	while (psl)//利用while循环遍历单链表
	{
		printf("%d->", psl->data);//打印单链表指向的数据
		psl = psl->next;//继续循环
	}
	printf("%d->NULL\n");//最后一个不要漏了
}

(4)单链表尾插

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
	assert(pplist);//断言二级指针
	SListNode* buy = BuySListNode(x);
	assert(buy);//判断节点是否开辟成功
	SListNode* psl= *pplist;//创建一个新的变量
	if (psl == NULL)//如果是一个节点都没有的情况
	{
		*pplist = buy;//需要将头指针改变(原本头指针是NULL)所以需要节点指针的指针
		return;
	}
	while (psl->next)//如果已经有节点的情况
	{
		psl = psl->next;//通过next遍历链表找到最后的节点
	}
	psl->next = buy;//将最后节点的next改成buy节点的指针,所以需要节点的指针即可,不需要二级指针

}

pplist是指向链表第一个节点指针的指针,是二级指针,所以一定不为空,要用assert断言;

(5)单链表头插

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
	assert(pplist);
	SListNode* buy = BuySListNode(x);
	assert(buy);//判断节点是否开辟成功
	SListNode* psl = *pplist;
	if (*pplist == NULL)//如果一个节点都没有的情况
	{
		*pplist = buy;//需要将头指针改变(原本头指针是NULL)所以需要节点指针的指针
		return;
	}
	//有节点的情况
	buy->next = psl;//需要通过next连接新节点
	*pplist = buy;//通过节点的指针的指针改变节点的指针
}

要注意有两种情况一直是没有一个节点的情况即*pplist = NULL,另一种是有节点的情况;

传二级指针的作用就是为了改变指针plist,所以需要指针的指针pplist;

(6)单链表尾删

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表的尾删
void SListPopBack(SListNode** pplist)
{
	assert(pplist);
	assert(*pplist);//删除节点要判断有没有节点
	SListNode* psl = *pplist;
	if (psl->next == NULL)//只有一个节点时
	{
		free(psl);//释放最后一个节点的空间
		*pplist = NULL;//尾指针置空
		return;
	}
	while (psl->next->next)//多个节点时找到倒数第二个节点
	{
		psl = psl->next;
	}
	free(psl->next);
	psl->next = NULL;//尾指针置空
}

单链表尾删同样要注意两种情况;使用free释放指针指向的空间;

(7)单链表头删

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表头删
void SListPopFront(SListNode** pplist)
{
	assert(pplist);
	assert(*pplist);//删除节点要判断有没有节点
	SListNode* psl = *pplist;
	if (psl->next == NULL)//只有一个节点时
	{
		free(psl);
		*pplist = NULL;
		return;
	}
	//多个节点时
	*pplist = psl->next;//将第二个节点的指针给头指针
	free(psl);//释放第一个节点的空间
}

(8)单链表查找

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
	assert(plist);//查找节点要判断有没有节点
	SListNode* psl = plist;
	while (psl)
	{
		if (psl->data == x)
		{
			return psl;//找到了返回psl
		}
		psl = psl->next;
	}
	return NULL;//没找到返回空指针
}

(9)单链表在pos位置之后插入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单链表在pos位置之后插入x

void SListInsertAfter(SListNode* pos, SLTDateType x)
{
	assert(pos);
	SListNode* buy = BuySListNode(x);
	assert(buy);//判断节点是否开辟成功
	//if (pos->next == NULL)
	//{
	//	pos->next = buy;//将最后节点的next改成buy节点的指针	
	//	return;
	//}
	buy->next = pos->next;//只有一个节点和多个节点一样
	pos->next = buy;
}

思考分析这两行代码可不可以调换一下顺序呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
buy->next = pos->next;//只有一个节点和多个节点一样
pos->next = buy;

答案是不能,我们看到如果交换顺序,先将buy赋值给pos->next,那么pos->next的值将会被改变,而我们需要在buy->next中保存原来的pos->next,所以不能调换顺序;

如果你想要换也可以通过创建一个临时变量来存储pos->next的方式实现.例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SListNode* cur = pos->next;
pos->next = buy;
buy->next = cur;

(10)单链表在pos位置之前插入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在pos的前面插入
void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{
	//assert(pphead);
	assert(pos);
	SListNode* buy = BuySListNode(x);
	assert(buy);//判断节点是否开辟成功
	SListNode* psl = *pphead;
	if (psl->next == NULL)//只有一个节点
	{
		buy->next = pos;
		*pphead = buy;
		return;

	}
	while (psl->next != pos)//多个节点
	{
		psl = psl->next;
	}
	buy->next = pos;
	psl->next = buy;
}

(11)单链表删除pos位置的节点

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 删除pos位置
void SLTErase(SListNode** pphead, SListNode* pos)
{
	assert(pos);
	SListNode* psl = *pphead;
	if (psl->next == NULL)//只有一个节点,类似于头删
	{
		free(pos);
		pos = NULL;
		*pphead = NULL;
		return;
	}
	while (psl->next != pos)//多个节点
	{
		psl = psl->next;
	}
	//此时psl->next = pos;
	psl->next = pos->next;将pos位置指向的下一个节点指针赋给psl->next
	free(pos);
	pos = NULL;

}

删除pos位置也要注意有两种情况;

(12)单链表销毁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void SLTDestroy(SListNode** pphead)
{
	assert(pphead);
	SListNode* psl = *pphead;
	SListNode* psll = *pphead;

	while (psl != NULL)
	{
		free(psll);
		psl = psl->next;
		psll = psl;
	}
	*pphead = NULL;
}

4.运行结果

5.结语

以上就是今天学习的内容了,单链表的实现关键在于理解它的逻辑结构,包括两个变量,一个是指向数据,另一个则指向下一节点的指针,此外,单链表实现还涉及了二级指针的内容以及动态内存函数的内容,涉及的代码知识更为广泛,但是只要抓住了关键点就会发现每个函数的中心思想都是不变的,好了以上就是今天学习的内容啦,有什么问题欢迎大家在评论区指出或者私信我哦~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【数据结构与算法】顺序表与链表详解
​ 线性表(linear list) 是 n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
利刃大大
2025/05/22
1040
【数据结构与算法】顺序表与链表详解
【初探数据结构】线性表————链表(一)(单链表的实现)
链表是一种物理存储结构非连续、非顺序的线性数据结构。与数组不同,链表的元素通过指针链接形成逻辑上的顺序关系。每个节点包含两部分:
我想吃余
2025/03/31
940
【初探数据结构】线性表————链表(一)(单链表的实现)
链表的实现(文末附完整代码)
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 我们在上一篇文章所学习的顺序表是连续存储的 例如: 顺序表就好比火车上的一排座位,是连续的 而链表就好比是火车的各节车厢,中间有东西将其互相连接的
ahao
2024/03/19
1360
链表的实现(文末附完整代码)
带你玩转数据结构-单链表(适合初学者的文章,讲解的很仔细哦)
链表的概念: 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.也是属于线性表的一种.
初阶牛
2023/05/10
3800
带你玩转数据结构-单链表(适合初学者的文章,讲解的很仔细哦)
[数据结构]——顺序表和链表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
小李很执着
2024/06/15
1090
[数据结构]——顺序表和链表
【数据结构初阶】单链表接口实现超详解
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
fhvyxyci
2024/09/24
1190
【数据结构初阶】单链表接口实现超详解
开卷数据结构?!单链表实现超详解~
目录 前言 链表 概念及结构 链表的实现 增删查改接口 节点结构体创建 链表节点开辟 链表数据打印 链表尾插数据 链表前删数据 链表数据查找 链表pos位置前插数据(较难) 链表pos位置后插数据(简单) 链表pos位置数据删除 链表节点释放 链表与顺序表区别 ---- 在这个特殊的日子里,祝各位程序员1024节日快乐~ 前言 ---- 本章我们将主要讲解: 单链表及其实现 注:如果还不会顺序表,这里附上链接:数据结构-顺序表实现超详解(小白也能看懂的保姆级教程~) 链表 ---- 概念及
用户9645905
2022/11/30
2660
开卷数据结构?!单链表实现超详解~
数据结构从入门到精通——链表
链表是一种常见的数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表的一个显著特点是,它不需要在内存中连续存储,因此可以高效地插入和删除节点。这种灵活性使得链表在许多应用中成为理想的选择,尤其是在需要动态调整数据结构大小的场景中。
鲜于言悠
2024/03/20
5900
数据结构从入门到精通——链表
数据结构入门(3)2.链表接口实现
原理:链表的结点所代表的是一个内存块,里面包含着该节点的值以及指向下一个结点地址的指针,用动态申请的方式更加方便,插入时只需要将前一个结点里的指针指向自己即可,但新结点刚创建时,里面的指针指向空,不要变为野指针。
对编程一片赤诚的小吴
2024/03/12
1310
数据结构入门(3)2.链表接口实现
【数据结构初阶】单链表的实现
单链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针依次连接而形成一段链表的
举杯邀明月
2023/04/12
3500
【数据结构初阶】单链表的实现
【C语言入门数据结构3】链表之单链表
由于数组的这些缺点,自然而然的就产生链表的思想了。 链表通过不连续的储存方式,自适应内存大小,以及指针的灵活使用,巧妙的简化了上述的内容。
阿伟@t
2023/10/10
2420
【C语言入门数据结构3】链表之单链表
【数据结构与算法】深入理解 单链表
数据域用于存储实际的数据(可以是任意类型的数据),而指针域则存储指向下一个节点的地址。
倔强的石头_
2024/12/06
2240
【数据结构与算法】深入理解 单链表
【初阶数据结构与算法】线性表之单链表的定义与实现
   链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,我们可以使用生活中的例子打个简单的比喻,如图:
TANGLONG
2024/11/19
1170
【初阶数据结构与算法】线性表之单链表的定义与实现
【数据结构】顺序表和链表
我们在C语言当中学过数组,其实呢,数组可以实现线性表,线性表理解上类似于数组,那么什么是线性表呢?线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
HABuo
2024/11/19
2660
【数据结构】顺序表和链表
数据结构之单链表(赋源码)
线性表的链式存储结构就可以解决这些问题,首先链式存储结构并不需要增容,而是使用多少数据申请多少空间,这一点就避免了时间和空间的浪费。
技匠晓晨
2024/11/26
650
数据结构之单链表(赋源码)
【数据结构实战】从零开始打造你的专属链表
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
f狐o狸x
2024/11/19
590
【数据结构实战】从零开始打造你的专属链表
C语言之单链表的实现以及链表的介绍
针对以上顺序表中存在的问题,有人就设计出了链表这一结构。下面我将就链表中结构最简单的单链表做一个详细的介绍。
用户10923276
2024/03/28
1180
C语言之单链表的实现以及链表的介绍
【数据结构与算法】单链表的增删查改(附源码)
aosei
2024/01/23
1430
【数据结构与算法】单链表的增删查改(附源码)
【数据结构】——单链表超详细介绍(小白必看!!!)
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,但链表在逻辑上是连续的,顺序的,而数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
用户11036582
2024/04/10
4740
【数据结构】——单链表超详细介绍(小白必看!!!)
数据结构--双链表
双链表是一种在节点之间通过两个指针进行连接的数据结构,每个节点都有两个指针:一个指向前一个节点,另一个指向下一个节点。带头节点的双链表在实际应用中非常常见,本文将详细介绍其实现方法,并提供完整的 C 语言代码示例。
平凡之路.
2024/10/09
1000
数据结构--双链表
推荐阅读
相关推荐
【数据结构与算法】顺序表与链表详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验