05|双链表:搜索链表中节点的速度还可以更快吗?
王健伟
你好,我是王健伟。
上节课,我们学习了单链表的相关操作,我们会用它来对数据进行顺序存储,如果需要频繁增加和删除数据,同样也可以用到单链表。而它也可以衍生出好多种链表结构,双链表(也称双向链表)就是其中一种。
在单链表中,有一个指针域用于指向后继节点。这带来的问题是,如果要寻找单链表中某个已知节点的前趋节点,就会比较繁琐了,我们必须从链表头出发开始寻找,算法的平均情况时间复杂度为 O(n)。
那要怎么解决这个问题呢?
在单链表的基础上,我们可以增加一个用于指向前趋节点的指针,也称为前趋指针,当然,第一个节点的前趋指针指向 nullptr,如果是带头节点的链表,那么就是头节点的前趋指针指向 nullptr。这样,当查找某个节点的前趋节点就会非常容易,查找算法的时间复杂度也会从 O(n) 变为 O(1)。
这种增加了前趋指针的链表,被称为双链表。如果画得形象一点,双链表(带头节点)数据存储的描述图应该如图 9 所示:
图9 带头节点的双链表数据存储描述图
双链表的很多操作和单链表相同,比如元素获取、求长度、判断是否为空、链表释放等操作,因为这些操作并不需要用到前趋指针。而有一些常用操作双链表与单链表不同,下面,我还是使用带头结点的代码实现方式,来实现双向链表。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
双链表是一种链表结构,相较于单链表,它引入了前趋指针,使得查找某个节点的前趋节点更加高效。本文通过简洁清晰的代码示例和图示,帮助读者快速了解双链表的结构和操作,为进一步深入学习和应用提供了基础。另外,文章还提到了双链表的翻转操作,鼓励读者通过参考单链表的翻转操作,对比两者的不同来独立完成双链表的翻转操作。双链表的特点包括寻找前趋节点的时间复杂度为O(1),存放前趋指针需要额外消耗存储空间,以及利用head指针和last指针进行节点查找的优势。通过本文的讲解,读者还可以对C++标准模板库中的list容器的工作原理以及优缺点有了非常清晰的认识。整体而言,本文通过对比单链表和双链表的操作,帮助读者更好地理解双链表的特点和优势。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《快速上手 C++ 数据结构与算法》,新⼈⾸单¥68
《快速上手 C++ 数据结构与算法》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(4)
- 最新
- 精选
- 雪无痕p->prior->next = p->net->prior = p,这里p->net应为p->next
作者回复: 感谢支持,麻烦编辑同学修正
2023-06-15归属地:北京 - Bruder_Jinvector容器和list容器有以下区别: (1)vector内存连续,list内存不连续 (2)vector会预分配内存,capacity为vector实际内存大小,list内存分配为实际数据大小 (3)vector内存达到capacity容量时将vector数组全部拷贝到新的capacity大小的内存区域,会比list多进行内存拷贝 (4)vector实现对应数组,因此可以直接下标访问vector[i],而list容器内存不连续因此无法下标访问;因此数据涉及大量的随机访问(读操作)则最好使用vector (5)vector插入删除中间元素时数组会整体移动,而list插入删除直接修改链表指针;因此高效插入删除时还是list好些
作者回复: 挺好的呦
2023-06-05归属地:广东 - Geek_7ba740可以理解为读多写少用vector,写多读少用list,不确定的话用vector吗
作者回复: 可以这么理解。👶
2023-04-08归属地:四川 - 铁甲依然在我写了双链表的反转代码 //双链表的链表反转 template<typename T> void DbLinkList<T>::ReverseList() { if (m_length < 1) { return; } DblNode<T>* pothersjd = m_head->next->next; //指向从第二个节点的后续节点 m_head->next->next = nullptr; //第一个节点的后续指点指针值为空 DblNode<T>* ptemp; while (pothersjd != nullptr) { ptemp = pothersjd; //临时节点 pothersjd = pothersjd->next; //第二节点后移动 ptemp->prior = m_head; //后一段节点的前驱节点值为头节点 ptemp->next = m_head->next; //后一段节点的后驱节点为头节点的后驱节点 m_head->next->prior = ptemp; //头节点前的前一段节点的前驱节点为新插入的节点 m_head->next = ptemp; //头节点的后驱节点为新插入的节点 } }2023-10-10归属地:广东
收起评论