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…

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

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

Java中常用的集合

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

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,…

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

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

前端学习(1614):oracle数据库管理

导入表 del_data文件 hr_cre文件 第二步导入 hr_popul.sql 最后导入 查询语句 创建表myemp create table myemp(id number(10),name varchar2(20) ) 运行结果 oracle管理工具 创建表myemp1 create table myemp1(id number(10) )

Warning: Multiple build commands for output file /xxx

今天注意到这个问题&#xff0c;如下&#xff1a; 在这里找到了答案&#xff1a;http://www.cnblogs.com/weilaikeji/archive/2013/10/15/3369709.html 解决步骤&#xff1a; 1.选择你的工程 2.选择target 3.点击 Build Phases 4.展开Copy Bundle Resources 5.删除里面的刚才提…

oracle之基本的sql_select语句全

查看表有哪些列 desc employees; 运行结果 基本sql语句 查询全部列 查询特定列 注意事项 算数运算符 查询伪表 select 8*4 from dual 运行结果 --查询十二个月的工资并1000 select last_name,salary,12*salary1000 from employees 运行结果 --查询日期 select sysdate,sys…

oracle之基本的sql_select语句之课后练习

SQL*PLUS命令可以控制数据库吗? 否&#xff01;下面的语句是否可以执行成功 可以 select last_name , job_id , salary as sal from employees; 下面的语句是否可以执行成功 可以 select * from employees; 找出下面语句中的错误 标点符号需要是英文格式下的。 select…

oracle之基本的过滤和排序数据

--查询对应的列 大于5000 select employee_id,last_name,salary from employees where salary>5000 运行结果 --查询对应的日期 select last_name,hire_date from employees where hire_date7-6月-1994 --查询对应的日期 select last_name,hire_date from employees --wh…

HDU 3435 KM A new Graph Game

和HDU 3488一样的&#xff0c;只不过要判断一下是否有解。 1 #include <iostream>2 #include <cstdio>3 #include <cstring>4 #include <algorithm>5 #include <vector>6 using namespace std;7 8 const int maxn 1000 10;9 const int INF 0x…

linux qt getpid,[QTA] Android 动态注入原理分析

一、前言Android 的 UI 自动化测试可以通过注入式和非注入式分别实现&#xff0c;通过注入式可以更加方便地与应用进行交互。QTA 团队提供的 Android UI 自动化测试框架QT4A, 是通过动态注入的方式来获取被测应用的控件树信息等&#xff0c;从而达到自动化测试的目的。本文主要…