数据结构之双向链表-1

简介: 数据结构之双向链表

引言

数据结构之路在链表章节,前面介绍过单链表,今天我们来介绍最复杂的链表——双向链表(Double Linked List)


链表的分类

88f4fb01fe132b0b8570acd4c2e8504d_c643302dbf3c4144a911c55d355d0b5b.png


虽然有这么多的链表的结构,但是我们实际中 最常用 还是 两种结构 : 单链表 和 双向带头循环链表

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

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

前面我们讲的单链表,就是无头单向非循环链表,而现在讲的双向链表,就是带头双向循环链表。


双向链表的结构


e474b32f161318b1140a2198a3cc3ebe_69a62e21912d4e02aa39b5f1dffef38e.png

注意: 这里的 “带头” 跟前面我们说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严谨,但是为了同学们更好的理解就直接称为单链表的头节点。

带头链表里的头节点,实际为“哨兵位” ,哨兵位节点 不存储任何有效元素 ,只是站在这里“放哨的”

“哨兵位”存在的意义:

遍历循环链表避免死循环


双向链表的实现

定义

与单链表不同,一个节点里有两个指针,分别指向前节点和后节点,实现双向


9f78a42af47045b199a61b8657a35708.png


创建新节点

创建新节点与单链表大致相同,抽离成函数方便创建节点


43f42bd3fd5647cd84838aedb0af1435.png


初始化

双向链表与单链表很大区别,就是在于初始化,创建哨兵位,而哨兵位不存储有效数据,所有这里存入-1,并让prev和next指针都指向自身


33a30efd520243a2afdcb38ece25a447.png


打印

首先assert断言,因为phead指向哨兵位,一定不为空,其次因为双向循环链表里没有NULL,所有停止条件就看哨兵位,当cur指针的下一个为哨兵位时,就代表走到尾部了


53a6c987b7f14a2c8c057b3032c7f4bb.png


尾插

双向循环结构在空链表插入时,带来了极大的便利。因为prev指针的存在,使得找尾十分方便,不用遍历链表,直接访问哨兵位的上一个节点即可


01a6b9e2e293440480de4a7dfbecef00.png


8e52f69b214f4810abac44545cd8cb1c.png


如果是单链表,是不是还要讨论空链表的特殊情况啊?但是,在双向循环链表中,上述代码就可包含所有情况。因为哨兵位的存在,使得链表一定不为空。

d3ec97c7803d4f808e3cbf6c65eb0fa2.png


同时,因为哨兵位的存在,我们不用传二级指针了,只用对结构体进行操作。怎么样,有没有发现双向链表的巨大优势?


运行结果

ade1b171c7a64d3cabefb2f3d7c1374d.png


头插

头插时,要注意的就是要先链接后一个节点,再链接前一个节点


4bffda338a50497da15ce0a5ea5e5ff2.png


fce89c1ee387427b944353baa765543b.png


运行结果


9690e213283d4e0086dd539dbb17311f.png


判断链表是否为空

删除值得注意的是,不能删除哨兵位,要不然后续都无法对链表进行操作,所以专门写个函数来判断除了哨兵位链表是否为空,再用assert断言返回值  


如果phead和phead->next相等,则为空,返回1,即为真 ;不相等,则不为空,返回0,即为假


ebe4fb8ddb73483593b94e703321aebf.png


尾删

经历过单链表,双向链表的尾删就显得太简单了。找尾tail直接往phead的上一位,同时创建tailPrev,在释放尾部节点后,双向链接哨兵位

fac7380be9e847dbbdd412063748046c.png


427a510512a940d1863e5850669e2157.png


运行结果


a40e0505e9c84de1b5f639e5c95f0fd4.png


头删

同样,双向链表的头删也很简单。 找头first往phead的下一位,再创建second,在释放头部空间后,双向链接哨兵位


54c77b115f0442ca92e5e44bd6f3dcf2.png


de83143e9c84418185209170d54b0bc9.png


运行结果

c6762be2096842478d7590e77f06e3ba.png

相关文章
|
16天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
44 4
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
1月前
|
存储 Java
数据结构第三篇【链表的相关知识点一及在线OJ习题】
数据结构第三篇【链表的相关知识点一及在线OJ习题】
25 7
|
1月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
23 3
|
1月前
|
算法 Java
数据结构与算法学习五:双链表的增、删、改、查
双链表的增、删、改、查操作及其Java实现,并通过实例演示了双向链表的优势和应用。
16 0
数据结构与算法学习五:双链表的增、删、改、查
|
16天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
36 0
【数据结构】——双向链表详细理解和实现
【数据结构】——双向链表详细理解和实现
|
1月前
|
存储 Java
【数据结构】链表
【数据结构】链表
18 1
|
1月前
|
存储 缓存
数据结构3——双向链表
数据结构3——双向链表
112 1