嵌入式团队培训-循环链表、双向链表

今天我问队长:咱们不是要讲循环链表和双向链表吗,什么时候讲。

队长:这周

我看看日历:今天周三(周日要讲)

好 《大话数据结构》 ,启动


  1. 好 我们来想一下,什么是循环链表

链表尾部可以指向头部

当然这个头部也不是非得有个头结点,也可以没有。

草 看了看书发现确实没什么好记的

我们来想想循环链表是干嘛的

你看 本来你获取第一个结点的时间复杂度是 O(1) ,获取最后一个结点的时间复杂度是O(n)

但是我是用了循环链表,我有个指针直接指向了尾结点,而且这个指针的下一个结点就是头结点(或者第一个元素结点)

这样我们直接省了头指针,因为第一个结点可以用尾指针指示出来。

下面是循环链表的结构,以及两个循环链表的拼接在这里插入图片描述
要注意的地方就是结点挂起和…结点挂起

  1. 好 我们再看看双向链表
    有的时候我们往往想走回头路
    但学单链表的时候我们发现,我们一旦经过了某个结点,想要再看到他一次,就要从头再来,显然,这样子很离谱,我从思学楼去食堂的路上发现博学广上站着一位清秀的小伙子,我想回头看一眼难不成还要先跑回思学楼?(博学广场在思学楼和食堂之间),显然我只需要走到博学广场就够了。
    实现的方法就是在每个结点中增加一个指针域,这个指针指向前一个结点

那么第一个结点的前驱指针指向何方呢,如果不是循环链表,指向 null 就可以了;如果是循环链表,指向链表尾结点

另一种情况:一个循环链表,只有一个头结点,或者说,只有一个元素结点,那么他的前驱指针和后继指针就都指向他本身。因为它的后继是它本身,它的前驱还是它本身。

插入结点
我们来看看插入结点的代码

在这里插入图片描述

s->prior = p; // 先将 s 和 p 以及 p->next 进行连接 这里只对 s 结点的指针进行了操作
s->next = p->next; // 同上
p->next->prior = s; // 更新 p 的后继结点的前驱指针域为 s,不是原来的 p ,而是 s
p->next = s; // 现在可以放心地更新 p->next 了

这里我们需要注意的是先后顺序
我们发现 p->next 在赋值给 s->next 之后并没有直接被赋值为 s,因为先一步的操作 p->next->prior = s; 我们还用到了 p->next (用于修改原下一结点的前驱指针域)

删除结点
删除很简单,直接更新 删除结点前一结点的后继指针域和 删除结点后一结点的前驱指针域

p->prior->next = p->next; // 原先是指向 p 的 现在往后移一位
p->next->prior = p->prior; // 原先也是指向 p 的 现在往前移一位
free(p); // 记得释放 p 的空间

猜你喜欢

转载自blog.csdn.net/weixin_45543674/article/details/110500789
今日推荐