【Weiss】【第03章】双链表例程

双链表因为多了个前向指针,需要考虑的特殊因素多了一倍

所以中间插入(这儿没写)和中间删除会比较复杂。

其它倒没什么特别的,代码如下。

测试代码

 1 #include <iostream>
 2 #include "double_linklist.cpp"
 3 using namespace std;
 4 using namespace doublelinklist;
 5 template class DList<int>;
 6 int main(void)
 7 {
 8     DList<int> number;
 9
10     //测试插入
11     cout << "/*additem()*/" << endl;
12     number.additem(2);
13     number.additem(3);
14     number.additem(5);
15     number.additem(7);
16     number.additem(11);
17     number.additem(13);
18     number.additem(17);
19     number.traverse();
20     cout << "\n" << flush;
21     number.reverse();
22     cout << "\n/*end*/\n\n" << flush;
23
24     //测试获取长度
25     cout << "/*length()*/" << endl;
26     cout << number.size() << endl;
27     cout << "/*end*/\n\n" << flush;
28
29     //测试获得头元素
30     cout << "/*getfirst()*/" << endl;
31     cout << number.getfirst() << endl;
32     cout << "/*end*/\n\n" << flush;
33
34     //测试删除存在的元素(头尾及中间元素各一)
35     cout << "/*remove()*/" << endl;
36     number.remove(2);
37     number.remove(5);
38     number.remove(17);
39     number.traverse();
40     cout << "\n" << flush;;
41     number.reverse();
42     cout << "\n/*end*/\n\n" << flush;
43
44     //测试删除不存在的元素
45     cout << "/*remove()*/" << endl;
46     number.remove(19);
47     cout << "/*end*/\n\n" << flush;
48
49     //测试清空,并测试从空表中删除元素
50     cout << "/*clear(),remove()*/" << endl;
51     number.clear();
52     number.remove(2);
53     cout << "/*end*/\n\n" << flush;
54
55     system("pause");
56 }

double_linklist_driver

实现代码

  1 #include <iostream>
  2 using namespace std;
  3 #ifndef DOUBLELINKLIST
  4 #define DOUBLELINKLIST
  5
  6 namespace doublelinklist
  7 {
  8
  9 //链表节点模板
 10 template <typename T> struct Node
 11 {
 12     Node<T>() : next(nullptr),prev(nullptr){}
 13     Node<T>(const T &item, Node<T>* ptrn = nullptr, Node<T>* ptrp = nullptr) : data(item), next(ptrn), prev(ptrp){}
 14     T data;
 15     Node<T>* next;
 16     Node<T>* prev;
 17 };
 18 //头节点及链表主体操作
 19 template <typename T> class DList
 20 {
 21 //构造函数
 22 public:
 23     DList<T>() : length(0), front(nullptr){}
 24 //接口
 25 public:
 26     //返回长度
 27     unsigned int size()const{ return length; }
 28     //返回头指针
 29     Node<T>* begin()const{ return front; }
 30     //判断是否为空
 31     bool empty()const{ return length == 0; }
 32     //获得头元素
 33     T getfirst()const{ return front->data; }
 34     //获得尾元素
 35     T getlast()const{ return rear->data; }
 36     //#查找元素所在地址
 37     Node<T>* find(const T &item)const;
 38     //#尾部加入新元素
 39     bool additem(const T &item);
 40     //#删除指定元素
 41     bool remove(const T &item);
 42     //#遍历顺序输出链表元素
 43     void traverse()const;
 44     //#遍历倒序输出链表元素
 45     void reverse()const;
 46     //清空链表
 47     void clear();
 48
 49 //辅助函数
 50 private:
 51     //#查找元素前驱
 52     Node<T>* find_prev(const T& item)const;
 53 //数据
 54 private:
 55     unsigned int length;
 56     Node<T>* front;
 57     Node<T>* rear;
 58 };
 59
 60 //如果元素为头元素或元素不存在则返回nullptr,否则返回前驱
 61 template <typename T> Node<T>* DList<T>::find_prev(const T& item)const
 62 {
 63     if (length == 0)
 64         return nullptr;
 65     if (front->data == item)
 66         return nullptr;
 67     for (Node<T>* iter = front; iter->next != nullptr; iter = iter->next)
 68     {
 69         if (iter->next->data == item)
 70             return iter;
 71     }
 72     return nullptr;
 73 }
 74 //调用find_prev,如果元素存在则返回地址,不存在则返回nullptr
 75 template <typename T> Node<T>* DList<T>::find(const T &item)const
 76 {
 77     Node<T>* iter = find_prev(item);
 78     if (length == 0)
 79         return nullptr;
 80     if (front->data == item)
 81         return front;
 82     return iter->next;
 83 }
 84 template <typename T> bool DList<T>::additem(const T &item)
 85 {
 86     Node<T>* pnew = new Node<T>(item);
 87     //原链表无元素
 88     //头尾指针均指向新节点,且新节点前后指针默认为nullptr
 89     if (length == 0)
 90         front = rear = pnew;
 91     else
 92     {
 93         rear->next = pnew;
 94         pnew->prev = rear;
 95         rear = pnew;
 96     }
 97     ++length;
 98     return true;
 99 }
100 //删除操作相对复杂
101 template <typename T> bool DList<T>::remove(const T &item)
102 {
103     //先判断链表是否空避免front->data未定义
104     if (length == 0)
105     {
106         cout << "No data!" << endl;
107         return false;
108     }
109     Node<T>* iter = find_prev(item);
110     //find_prev返回nullptr,且首元素不等,说明链表中无此元素
111     if (iter == nullptr && front->data != item)
112     {
113         cout << "Can not find!" << endl;
114         return false;
115     }
116     Node<T>* save;
117     //如果元素是首元素
118     //则仅需将save后继(如果存在)的前向指针改为nullptr
119     //如果save无后继,说明链表删除后为空,将rear置空
120     if (front->data == item)
121     {
122         save = front;
123         front = front->next;
124         if (save != rear)
125             save->next->prev = nullptr;
126         else
127             rear = nullptr;
128     }
129     //如果元素不是首元素
130     //则save的前驱iter的后向指针需改指向save后继
131     //同时,save后继(如果存在)的前向指针改为指向save的前驱iter
132     //如果save无后继,则rear要指向新的尾节点
133     else
134     {
135         save = iter->next;
136         iter->next = save->next;
137         if (save != rear)
138             save->next->prev = iter;
139         else
140             rear = iter;
141     }
142     delete save;
143     --length;
144     return true;
145 }
146 template <typename T> void DList<T>::traverse()const
147 {
148     if (length != 0)
149     {
150         for (Node<T>* iter = front; iter != nullptr; iter = iter->next)
151             cout << iter->data << ends;
152     }
153 }
154 template <typename T> void DList<T>::reverse()const
155 {
156     if (length != 0)
157     {
158         for (Node<T>* iter = rear; iter != nullptr; iter = iter->prev)
159             cout << iter->data << ends;
160     }
161 }
162 template <typename T> void DList<T>::clear()
163 {
164     Node<T>* iter;
165     while (front != nullptr)
166     {
167         iter = front;
168         front = front->next;
169         delete iter;
170     }
171     front = rear = nullptr;
172     length = 0;
173 }
174 }
175 #endif
时间: 2025-01-14 10:22:38

【Weiss】【第03章】双链表例程的相关文章

【Weiss】【第03章】链表例程的一些修改

主要是,感觉原来的链表例程通过Node的分配形成了链表,但是没有自动消除Node的办法比较危险,一旦在clear()之前把链表赋了其它值就内存泄漏了. 所以改了析构函数,自动清理分配出来的内存.既然改了析构同时就要改拷贝合成与拷贝赋值. 然后还给链表加了个尾指针,否则每次插入都要O(N)的时间真的很蛋疼……改了以后就是O(1)了 栈.队列.双链表的到时候再改. 添加的构造函数.赋值函数.析构函数如下: 1 //构造函数,这部分直接增加在链表内部 2 public: 3 //拷贝构造函数,深拷贝

【Weiss】【第03章】链表例程

这种基础例程,如之前所提,会有一个实现和一个简单的测试代码. 链表其实没什么可说的,其实包括后面的栈和队列也没什么可说的,直接放代码吧. 下面这个是测试代码 1 #include <iostream> 2 #include "linklist.cpp" 3 using namespace std; 4 using namespace linklist; 5 template class List<int>; 6 int main(void) 7 { 8 List

【Weiss】【第03章】队列例程

前几个例程还是相当简单的,把链表即时改了一下就是队列了. 还有想了一下,决定这种例程的代码放法是:先把测试代码默认折叠放在前面,然后把实现代码默认展开放在后面. 测试代码如下: 1 #include <iostream> 2 #include "queue.cpp" 3 using namespace std; 4 using namespace queue; 5 template class Queue<int>; 6 int main(void) 7 { 8

【Weiss】【第03章】栈例程

写栈比队列更简单一些,毕竟只有一个数据出入口. 之前用C在程序里模拟栈代替递归的时候,直接搞个数组来实现都是非常轻松愉快的事情. 不多说,放代码. 测试代码 1 #include <iostream> 2 #include "stack.cpp" 3 using namespace std; 4 using namespace stack; 5 template class Stack<int>; 6 int main(void) 7 { 8 Stack<

【Weiss】【第03章】练习3.3

[练习3.3] 通过之调整指针(而不是数据)来交换两个相邻的元素,使用 a.单链表 b.双链表

【Weiss】【第03章】练习3.2

[练习3.2] 给你一个链表L和另一个链表P,它们包含以升序排列的整数.操作printlots(L,P)将打印L中那些由P所指定的位置上的元素. 例如,如果p=1,3,4,6,那么,L的第一.第三.第四和第六个元素被打印出来. 你应该只使用基本的表操作,该过程的运行时间是多少? Answer: 老样子,先放折叠的实测代码. 1 #include <iostream> 2 #include <string> 3 #include "linklist.cpp" 4

深度解析(三)数组、单链表和双链表

数组.单链表和双链表介绍 以及 双向链表的C/C++/Java实现 概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现.内容包括:数组单向链表双向链表1. C实现双链表2. C++实现双链表3. Java实现双链表 数组 数组有上界和下界,数组的元素在上下界内是连续的. 存储10,20,30,40,50的数组的示意图如下: 数组的特点是:数据是连续的

优先双链表

题目: 设有一个双链表,每个结点中除有prior,data和 next这3个域外,还有一个访问频度域 freq,在链表被启用前其值均初始化为0.每当在在链表上进行一次查找操作Locate(L, x)时,令元素值为x的结点中的freq域的值增加1,并使此链表中的结点保持按访问频度域递减的顺序排列,以便使频繁访问的结点总是靠近表头 (1)首先创建一个双链表. (2) 设计一个符合上述要求的Locate(L, x)函数. (3) 具有输出显示访问频度功能. (4) 要求程序通过一个主菜单进行控制,在主

java数据结构与算法之双链表设计与实现

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/53047590 出自[zejian的博客] 关联文章: 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) ??上一篇文章分析顺序表和单链表,本篇就接着上篇继续聊链表,在单链表