3.2 双向链表

1.简介 

前面3.1的单链表在操作过程中有一个缺点,就是后面的节点无法直接找到前面的节点,这使很多操作都得从头到尾去搜寻节点,算法效率变得非常低,解决这个问题的方法就是重新定义链表的节点使每个节点有两个指针,一个指向前驱一个指向后驱,这就是双向链表。

节点定义
  1. template<class T>
  2. class DLLNode {
  3. public:
  4. DLLNode() {
  5. next = prev = 0;
  6. }
  7. DLLNode(const T& el, DLLNode<T> *n = 0, DLLNode<T> *p = 0) {
  8. info = el; next = n; prev = p;
  9. }
  10. T info;
  11. DLLNode<T> *next, *prev;
  12. };

3.1节中所定义方法的局限性是链表只能存储整数. 如果希望链表存储浮点数点数或者数组.就必须重新写一套类似的代码。然而,更好的做法是只对这样的类声明一次,并且不提前确定其中存储什么数据类型,在 C++中,用模板就能很方便地做到这一点 。 为了说明模板在链表处理中的用法, 从本节开始使用模版来定义链表,但链表操作的示例仍然采用存储整数的链表。

2.双向链表的操作

DoublyLinkedList类定义了双向链表的操作
  1. template<class T>
  2. class DoublyLinkedList {
  3. public:
  4. DoublyLinkedList() {
  5. head = tail = 0;
  6. }
  7. void addToDLLTail(const T&);//插入节点到双向链表结尾
  8. T deleteFromDLLTail();//删除末尾的节点并返回其值

  9. ~DoublyLinkedList() {
  10. clear();
  11. }
  12. bool isEmpty() const {
  13. return head == 0;
  14. }
  15. void clear();
  16. void setToNull() {
  17. head = tail = 0;
  18. }
  19. void addToDLLHead(const T&);
  20. T deleteFromDLLHead();
  21. T& firstEl();
  22. T* find(const T&) const;
  23. protected:
  24. DLLNode<T> *head, *tail;
  25. friend ostream& operator<<(ostream& out, const DoublyLinkedList<T>& dll) {
  26. for (DLLNode<T> *tmp = dll.head; tmp != 0; tmp = tmp->next)
  27. out << tmp->info << ' ';
  28. return out;
  29. }
  30. };

这里只讨论两种操作方法:插入节点到双向链表结尾和删除末尾的节点,其余操作方法读者可以自行参考代码。
(1)插入节点到双向链表结尾


具体分为下面几个步骤:
  • 创建一个新的节点并初始化三个数据成员(info初始化为el,next初始化为null)
  • 将prev的值设置为tail
  • 将tail指向新加入的节点
  • 前驱节点的next指向新加入的节点
  1. template<class T>
  2. void DoublyLinkedList<T>::addToDLLTail(const T& el) {
  3. if (tail != 0) {
  4. tail = new DLLNode<T>(el,0,tail);
  5. tail->prev->next = tail;
  6. }
  7. else head = tail = new DLLNode<T>(el);
  8. }
(2)删除末尾的节点


双向链表删除一个末尾节点比较简单,因为不需要通过循环来查找待删除节点的前驱节点,将tail指向待删除节点的前驱,
然后将待删除节点的next设置为null。但是如果待操作的链表是空链表可能会引起程序崩溃,因此使用者在删除末尾节点之前要先检查链表是否为空,检查链表是否为空,代码中也提供了。
  1. if (!list.isEmpty())
  2. n = list.deleteFromDLLTail();
  3. else do not delete;
另一种特殊情况是链表只有一个节点,要将head和tail设置为空。

因为可以直接访问最后一个节点,因此这两个方法执行的时间复杂度为O(1)。
完整代码见:http://www.oschina.net/code/snippet_588162_48663


来自为知笔记(Wiz)


附件列表

 

转载于:https://www.cnblogs.com/star91/p/4761752.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/419628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uc通讯不成功php版本过高,Ucenter通信失败排查方法

定位错误来源&#xff1a;1. 使用firebug或类似于firebug的工具审查”通信失败“这几个字2. 会发现包含这几个字的div的同级下方有个script标签&#xff0c;复制该script标签的src值到浏览器的新标签页并打开3. 这个url指向的是ucenter中app模块的onping操作(ucenter/control/a…

马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别

马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别 http://martinfowler.com/articles/injection.html 中文翻译&#xff1a;http://files.cnblogs.com/files/stono/DependencyInjection.pdf 转载于:https://www.cnblogs.com/stono/p/4764551.html

oracle工作流错误,工作流错误处理 - Oracle® ZFS Storage Appliance 客户服务手册

工作流错误处理如果在执行工作流期间发生错误&#xff0c;则会引发异常。如果异常未由工作流自身所捕获(或者如果工作流引发的异常未以其他方式捕获)&#xff0c;则工作流将失败&#xff0c;并向用户显示有关异常的信息。要正确处理错误&#xff0c;应该捕获并处理异常。例如&a…

敏捷软件开发:原则、模式与实践——第12章 ISP:接口隔离原则

第12章 ISP&#xff1a;接口隔离原则 不应该强迫客户程序依赖并未使用的方法。   这个原则用来处理“胖”接口所存在的缺点。如果类的接口不是内敛的&#xff0c;就表示该类具有“胖”接口。换句话说&#xff0c;类的“胖”接口可以分解成多组方法。每一组方法都服务于一组不…

pxe安装linux后命令不可用,pxe自动安装linux

配置自动安装操作系统1.网卡应支持pxe技术&#xff0c;由网卡作为dhcp的客户端向dhcp服务器请求一个IP地址&#xff0c;dhcp会将ip&#xff0c;网关等信息和的tftp服务器的地址应加载的文件名提供给客户端2.根据dhcp服务器提供的信息网卡上内置的tftp客户端向tftp服务器发出请求…

Java中常用的集合

有序列允许元素重复否Collection否是List是是SetAbstractSet否      否HashSetTreeSet是&#xff08;用二叉树排序&#xff09;MapAbstractMap否 使用key-value来映射和存储数据&#xff0c; Key必须惟一&#xff0c;value可以重复 HashMapTreeMap是&#xff08;用二叉树…

linux文件系统的设计,基于Linux的文件系统设计.doc

PAGEPAGE 33无敌操作系统课程设计说 明 书?学 院、系&#xff1a;软件学院专 业&#xff1a;软件工程学 生 姓 名&#xff1a;学 号&#xff1a;设 计 题 目&#xff1a;基于Linux的模拟文件系统的设计与实现起 迄 日 期:指 导 教 师:?PAGEPAGE 33PAGE \* MERGEFORMATPAGE \*…

ASP.NET MVC必知必会知识点总结(二)

一、实现Controller的依赖注入&#xff1a; 1.自定义继承DefaultControllerFactory 类的控制器工厂类并重写GetControllerInstance方法&#xff1b;&#xff08;如&#xff1a;InjectControllerFactory&#xff09; 2.在Global.asax文件中的Application_Start方法中注册该控制器…

linux客户端无法绑定端口号,为什么Linux客户端的情况下不支持端口共用?

也不是不可以, 如果是socket的话只要设置端口复用就可以实现&#xff0c;随便写一段代码演示一下#/bin/pythonimport sysimport timeimport socketdef start_tcp_client(ip, port):#server port and ipserver_ip ipservr_port porttcp_client socket.socket(socket.AF_INET,…

如何提取pdf中的文字图片转为word文档

大家都知道图片形式的PDF文件中的文字是无法直接复制的&#xff0c;可是很多时候我们必须得将PDF里面的文本转成Word文档格式&#xff0c;如何才能实现呢?其实不难&#xff0c;首先你要保证PDF里面的图片文字足够清晰&#xff0c;然后利用专业的PDF文件转换工具即可。什么是PD…

基于Linux系统的手机,中国最新超算操作系统揭秘:基于Linux

世界第一超级计算机神威太湖之光亮相之后&#xff0c;令世界瞩目。这款超级计算机由中国自主研发&#xff0c;处理器采用64位国产260核CPU申威SW26010&#xff0c;性能几乎是天河2号的三倍&#xff0c;但总功耗反而更低。这款超算不仅有强悍无比的硬件&#xff0c;更有神通广大…

ubuntu ssh 免密码登陆

ssh-keygen -t rsa //一路回车就好 cat id_dsa.pub >> ~/.ssh/authorized_keys 修改ssh配置文件(这一步很重要,不然可能不生效) sudo vi /etc/ssh/sshd_config AuthorizedKeysFile %h/.ssh/authorized_keys //取消前面注释 sudo service ssh restart 转载于:htt…

linux日志不区分大小写,windows系统迁移到linux下,Nginx实现url请求不区分大小写...

如果你将跑在Windows下的项目(如&#xff1a;php、html)迁移到Linux下&#xff0c;由于Windows操作系统中&#xff0c;文件名是不区分大小写的&#xff1b;而Linux系统是大小写敏感&#xff0c;会导致有些网页出现404情况。 解决方法有大概4种&#xff1a; 1、 url rewrite 2、…