一:什么是双向循环链表
二:实现双向循环链表
补充:实现双向循环链表的销毁,打印
一:什么是双向循环链表
我问问你什么是链表呢?链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。它的特征无非是物理结构非连续,非顺序,逻辑顺序是通过指针链接的,也就意味着可以任意位置插入删除数据。
它由一个个节点构成,每个节点存放数据和地址
如下是最简单的单链表,大家可以结合图片理解
我们今天实现的双向循环链表拥有单链表的特征,只不过多了头节点,循环,是不是看起来复杂些,它的用处大的很呢!嘿嘿。
二:接下来让我们来会一会这个双向循环链表
我们知道双向循环链表头节点,循环,也就是有哨兵位,前继指针,后继指针,同时他们是定义双向链表节点的结构三元素。
有了三元素坐镇,可以定义双向循环链表啦。
定义一个双向循环链表,我们先创建哨兵位,哨兵位即为头节点,它并不存储有效数据,只起到占位置的作用,然后在将所需数据接到头节点之后。
哨兵位也有注意的点,哨兵位是双向循环链表起始位置,如果没有哨兵位,这个链表是不存在的;哨兵位可以单独存在,所以双向循环链表不存在为空情况。
在初始化双向循环链表时,链表为空什么都没有,当然得放进哨兵位来占位置咯,它不存储有效数据哦
我们在申请空间存放节点时要判断一下节点是否为空,为啥要判断节点为空呢?因为如果节点为空,那么他连哨兵位都没有了,就不构成哨兵位。
定义好双向循环链表,那就开始增删查改的工作吧!
二:
a.尾插
首先明确,尾插发生变动的地方,一个是哨兵位,一个是尾节点,一个是新节点。先插新节点,因为尾插入新节点对链表没啥影响,newnode前趋指针指向尾,后趋指针指向哨兵位,将为节点后趋指针指向newnode,phead前趋指针指向newnode,这样完成了尾插
这是代码
这是尾插的调试,通过调试来判断代码逻辑正确性
b.头插
将节点插入到第一个有效节点之前。而不是哨兵位节点之前,如果插到哨兵位之前,交换了newnode的位置,指针的指向并没有发生改变,到头来还是尾插。
头插
让代码运行一下吧
链表打印:
尾删:
顾名思义是删除尾节点,我们不可以直接删除尾节点,而是要先保存尾节点,然后在删除尾节点。具体步骤如下:
让尾插代码跑起来吧
头删
头删,删除的是有效节点,即哨兵位之后的节点,下图中,要删的节点是d1
怎么删呢,不能直接删d1,因为head->next指向d1,d2指向d1,在删除之前,先保存d1,然后删
双向链表的查找
因为双向链表的哨兵位节点不存放有效数据,所以从哨兵位的下一个节点开始查找数据,当指针指向所需要的数据,表明查找成功,否则失败
让代码运行一下吧
g.1在pos前插入数据
pos是有效节点,它不可能是哨兵位。在pos后插入数据所用的方试类似于头插,头插那一套在这里同样适用。
g.2 pos后插入数据
原理跟pos前插入数据一样,只不过换了位置
删除pos节点
不能直接删掉pos,要先保留pos前一个节点以及后一个节点,然后前一个节点指向后一个节点,后一个节点指向前一个节点