天天看点

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

@toc

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 前面说到,链表的结构一共有八种:带头单向循环链表、带头单向非循环链表、带头双向循环链表、带头双向非循环链表、无头单向循环链表、无头单向非循环链表、无头双向循环链表、无头双向非循环链表。

 在这八种结构中,只挑两种来进行刨析,即<code>无头单向非循环链表</code>和<code>带头双向循环链表</code>。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

前面我们实现了无头单向非循环链表,特性为:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在oj题中出现很多,所以我们才要模拟实现充分了解它的特性。

而无头单向非循环链表是有缺点的,那就是尾插和尾删的时候都要找到最后一个结点,时间复杂度为o(n),并且要考虑到是否为头结点删除起来很不方便。

<code>针对这一些缺点我们再来实现带头双向循环链表,带头双向循环链表结构复杂,一般用在单独存储数据,结构复杂了一点,但是实现起来却很简单。</code>

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

和前面实现无头单向非循环链表类似,我们也要创建创建一个结点数据类型,里面为数据域和指针域,不过指针域里面要存放上一个结点的地址和下一个结点的地址。

因为我们的链表是带头的,所以我们在初始化的时候需要开辟一个头结点出来

头结点的特征:不存储有效数据,所以我们初始化的时候不需要初始化头结点中的数据

我们为了满足循环的特征,将头结点的next和prev都指向自己

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

这一小部分主要是链表的销毁或者清除,这两唯一不同的区别就是:

==destroy==是把所有结点都删除且没有保留头结点,不能继续使用

==clear==保留了头结点,允许继续使用。所以destroy需要将头结点置空,所以需要用二级指针传址调用来改变一级指针从而达到将传递的指针置空的效果。

代码如下:

 打印双向链表时也是从头结点的后一个结点处开始向后遍历并打印,直到遍历到头结点处时便停止遍历和打印(头结点数据不打印)。

 给定一个值,在链表中寻找与该值相同的结点,若找到了,则返回结点地址;若没有找到,则返回空指针(null)。

 头插,即申请一个新结点,将新结点插入在头结点和头结点的后一个结点之间即可。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 尾插,申请一个新结点,将新结点插入到头结点和头结点的前一个结点之间即可。因为链表是循环的,头结点的前驱指针直接指向最后一个结点,所以我们不必遍历链表找尾。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 在直到位置插入结点,准确来说,是在指定位置之前插入一个结点。我们只需申请一个新结点插入到指定位置结点和其前一个结点之间即可。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 头删,即释放头结点的后一个结点,并建立头结点与被删除结点的后一个结点之间的双向关系即可。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 尾删,即释放最后一个结点,并建立头结点和被删除结点的前一个结点之间的双向关系即可。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 删除指定位置结点,释放掉目标结点后,建立该结点前一个结点和后一个结点之间的双向关系即可。

【数据结构】——拿捏链表 ( 带头双向循环链表 )⌛链表介绍⌛⌚一、带头双向循环链表介绍⛲二、带头双向循环链表实现思路

 链表判空,即判断头结点的前驱或是后驱指向的是否是自己即可。

 获取链表中的元素个数,即遍历一遍链表,统计结点的个数(头结点不计入)并返回即可。

继续阅读