前言
学会了单链表后,我们可以进一步了解双向链表。
读者有任何关于双向链表的问题可以私信博主哦,最后附带源码。
1.什么是双向链表
双向链表全称是双向带头循环链表。带头指的是有一个哨兵位结点,该结点不存储有效的数据,作哨兵作用。
双向链表的结构如下:
双向链表每个结点有两个指针,一个next指针指向后面的结点,一个prev指针指向前面结点。哨兵位的prev指针指向尾结点,尾结点的next指针指向哨兵位。
2. 双向链表的实现
2.1 结构体的定义
我们还是将链表和数据进行重命名,为了后面更好的使用。结构体里面需要有两个结构体指针,以及结点存储的数据。
2.2 申请新结点
申请新结点我们在之前实现链表的时候已经实现过了,这里不再细讲。
2.3 创建双向链表
我们创建头结点只需要申请一个头结点,因为头结点的值不需要有价值,我们通常用-1表示。
需要注意,我们需要改变头结点,所以需要传二级指针地址。
2.4 头插
头插不需要考虑链表是否为空,只需要在头结点后面插入就行。头插需要改变的只有头结点的一个next指针和头结点的下一个指针的prev指针以及newnode的两个指针。由于先修改前两者会造成覆盖现象,我们一般先改变newnode的指针,再改变头结点的下一个结点的prev指针,最后改变头结点的next指针。
2.5 尾插
尾插影响的是尾部结点,即pphead->prev,pphead和newnode。我们还是先修改newnode的指针再修改prev的指针,最后再修改pphead的指针。
2.6 头删
头删需要链表不为空,即不止有头结点。头删影响的有头结点的next指针,pphead->next->prev。改完指向后别忘记free掉结点并将其置为空。
2.7 尾删
尾删也需要链表不为空。尾删影响的是尾指针和头指针以及尾结点的前一个结点的next指针。
修改完指针后将尾指针free掉并将其置为空。
2.8 查找指定位置
查找到指定位置有利于删除指定位置以及指定位置后插入。
需要先判断给的链表是否正确。让pcur从头结点的下一个结点开始遍历链表,当回到头结点的时候还没有找到结点便返回失败。找到则返回位置。
2.9 删除指定位置
判断一下位置是否正确。直接将pos前的结点next指向pos的后面结点,并将pos的后面结点的prev指向pos的前面结点,最后free掉pos将其置为空。
2.10 指定位置后插入
先判断pos是否正确。影响的是pos以及pos的next指针指向的结点以及newnode。先修改newnode,再修改next,最后修改pos结点的指针。