单链表、双链表及单链表的逆序

参考博客:数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

              单向链表逆序

一、单链表

单链表结构如下图:

本文中,head节点也是包含数据的,并且最后一个节点指向的指针为NULL。

下图为单链表的删除操作:

下图为单链表的插入操作:

单链表的实现代码如下:

  1 #ifndef SINGLE_LINK_H
  2 #define SINGLE_LINK_H
  3 
  4 #include <iostream>
  5 using namespace std;
  6 
  7 template<class T>
  8 struct SNode
  9 {
 10 public:
 11     T data;
 12     SNode *next;
 13     SNode(){}
 14     SNode(T data, SNode *next)
 15     {
 16         this->data = data;
 17         this->next = next;
 18     }
 19 };
 20 
 21 template<class T>
 22 class SingleLink
 23 {
 24     public:
 25         SingleLink();
 26         ~SingleLink();
 27 
 28         SNode<T> *getHeadNode();
 29         void setHeadNode(SNode<T> *head);
 30         int getSize();
 31         bool isEmpty();
 32         T get(int index);
 33         T getFirst();
 34         T getLast();
 35         void insert(int index, T t);
 36         void insertFirst(T t);
 37         void appendLast(T t);
 38         void del(int index);
 39         void deleteFirst();
 40         void deleteLast();
 41 
 42     private:
 43         int count;
 44         SNode<T> *pHead;
 45         SNode<T> *getNode(int index);
 46 };
 47 
 48 template<class T>
 49 SingleLink<T>::SingleLink() : count(0)
 50 {
 51     pHead = new SNode<T>();
 52     pHead->next = NULL;
 53 }
 54 
 55 template<class T>
 56 SingleLink<T>::~SingleLink()
 57 {
 58     SNode<T> *ptmp;
 59     while(pHead->next != NULL)
 60     {
 61         ptmp = pHead;
 62         pHead = pHead->next;
 63         delete ptmp;
 64     }
 65 
 66     delete pHead;
 67     pHead = NULL;
 68 }
 69 
 70 template<class T>
 71 int SingleLink<T>::getSize()
 72 {
 73     return count;
 74 }
 75 
 76 template<class T>
 77 bool SingleLink<T>::isEmpty()
 78 {
 79     return count == 0;
 80 }
 81 
 82 template<class T>
 83 SNode<T> *SingleLink<T>::getNode(int index)
 84 {
 85     if(index < 0 || index >= count)
 86     {
 87         cout << "Get node failed! The index in out of bound!" << endl;
 88         return NULL;
 89     }
 90 
 91     SNode<T> *pindex = pHead;
 92     int i = 0;
 93     while(i++ < index)
 94     {
 95         pindex = pindex->next;
 96     }
 97 
 98     return pindex;
 99 }
100 
101 template<class T>
102 SNode<T> *SingleLink<T>::getHeadNode()
103 {
104     return getNode(0);
105 }
106 
107 template<class T>
108 void SingleLink<T>::setHeadNode(SNode<T> *head)
109 {
110     this->pHead = head;
111 }
112 
113 template<class T>
114 T SingleLink<T>::get(int index)
115 {
116     return getNode(index)->data;
117 }
118 
119 template<class T>
120 T SingleLink<T>::getFirst()
121 {
122     return getNode(0)->data;
123 }
124 
125 template<class T>
126 T SingleLink<T>::getLast()
127 {
128     return getNode(count - 1)->data;
129 }
130 
131 template<class T>
132 void SingleLink<T>::insert(int index, T t)
133 {
134     SNode<T> *pnode;
135 
136     if(index == 0)
137     {
138         insertFirst(t);
139     }
140     else if(index == count)
141     {
142         appendLast(t);
143     }
144     else
145     {
146         SNode<T> *pindex = getNode(index - 1);
147         pnode = new SNode<T>(t, pindex->next);
148         pnode->data = t;
149         pindex->next = pnode;
150         count++;
151     }
152 }
153 
154 template<class T>
155 void SingleLink<T>::insertFirst(T t)
156 {
157     if(count == 0)
158     {
159         pHead->data = t;
160     }
161     else
162     {
163         SNode<T> *pnode = new SNode<T>(t, pHead);
164         pHead = pnode;
165     }
166     count++;
167 }
168 
169 template<class T>
170 void SingleLink<T>::appendLast(T t)
171 {
172     SNode<T> *pindex = getNode(count - 1);
173     SNode<T> *pnode = new SNode<T>();
174     pindex->next = pnode;
175     pnode->data = t;
176     pnode->next = NULL;
177     count++;
178 }
179 
180 template<class T>
181 void SingleLink<T>::del(int index)
182 {
183     if(index >= count)
184     {
185         cout << "The index in out of bound!" << endl;
186     }
187     else
188     {
189         SNode<T> *pindex = getNode(index - 1);
190         SNode<T> *ptmp = pindex->next;
191         pindex->next = pindex->next->next;
192         delete ptmp;
193         ptmp = NULL;
194         count--;
195     }
196 }
197 
198 template<class T>
199 void SingleLink<T>::deleteFirst()
200 {
201     if(count == 0)
202     {
203         cout << "This single link is null!";
204         return;
205     }
206     SNode<T> *ptmp = pHead;
207     pHead = pHead->next;
208     delete ptmp;
209     ptmp = NULL;
210     count--;
211 }
212 
213 template<class T>
214 void SingleLink<T>::deleteLast()
215 {
216     del(count - 1);
217 }
218 
219 #endif
View Code

测试代码如下:

  1 #include <iostream>
  2 #include <string>
  3 #include "DoubleLink.h"
  4 #include "SingleLink.h"
  5 using namespace std;
  6 
  7 void IntTest()
  8 {
  9     cout << "\n----IntTest----" << endl;
 10 
 11     SingleLink<int> *pdlink = new SingleLink<int>();
 12 
 13     pdlink->insert(0, 20);
 14     pdlink->appendLast(10);
 15     pdlink->insertFirst(30);
 16 
 17     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 18 
 19     cout << "size() = " << pdlink->getSize() << endl;
 20 
 21     int sz = pdlink->getSize();
 22     for(int i = 0; i < sz; i++)
 23     {
 24         cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
 25     }
 26 
 27     delete pdlink;
 28 }
 29 
 30 void StringTest()
 31 {
 32     cout << "\n----StringTest----" << endl;
 33 
 34     string sarr[3] = {"ten", "twenty", "thirty"};
 35 
 36     SingleLink<string> *pdlink = new SingleLink<string>();
 37 
 38     pdlink->insert(0, sarr[0]);
 39     pdlink->appendLast(sarr[1]);
 40     pdlink->insertFirst(sarr[2]);
 41 
 42     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 43 
 44     cout << "size() = " << pdlink->getSize() << endl;
 45 
 46     int sz = pdlink->getSize();
 47     for(int i = 0; i < sz; i++)
 48     {
 49         cout << "pdlink(" << i << ") = " << pdlink->get(i) <<endl;
 50     }
 51 
 52     delete pdlink;
 53 }
 54 
 55 struct stu
 56 {
 57     int id;
 58     char name[20];
 59 };
 60 
 61 static stu arr_stu[] =
 62 {
 63     {10, "sky"},
 64     {20, "jody"},
 65     {30, "vic"},
 66 };
 67 
 68 void ObjectTest()
 69 {
 70     cout << "\n----ObjectTest----" << endl;
 71 
 72     SingleLink<stu> *pdlink = new SingleLink<stu>();
 73 
 74     pdlink->insert(0, arr_stu[0]);
 75     pdlink->appendLast(arr_stu[1]);
 76     pdlink->insertFirst(arr_stu[2]);
 77 
 78     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 79 
 80     cout << "size() = " << pdlink->getSize() << endl;
 81 
 82     int sz = pdlink->getSize();
 83     struct stu p;
 84     for(int i = 0; i < sz; i++)
 85     {
 86         p = pdlink->get(i);
 87         cout << "pdlink(" << i << ") = [" << p.id << ", " << p.name << "]" << endl;
 88     }
 89 
 90     delete pdlink;
 91 }
 92 
 93 int main()
 94 {
 95     IntTest();
 96     StringTest();
 97     ObjectTest();
 98 
 99     return 0;
100 }
View Code

二、双链表

双链表的结构如下:

本文的实现中,head节点作为一个特殊节点,不存储数据。

下图为双链表的删除操作:

下图为双链表的插入操作:

双链表的实现代码如下:

  1 #ifndef DOUBLE_LINK_H
  2 #define DOUBLE_LINK_H
  3 
  4 #include <iostream>
  5 using namespace std;
  6 
  7 template<class T>
  8 struct DNode
  9 {
 10     public:
 11         T value;
 12         DNode *prev;
 13         DNode *next;
 14     public:
 15         DNode(){}
 16         DNode(T t, DNode *prev, DNode *next)
 17         {
 18             this->value = t;
 19             this->prev  = prev;
 20             this->next  = next;
 21         }
 22 };
 23 
 24 template<class T>
 25 class DoubleLink
 26 {
 27     public:
 28         DoubleLink();
 29         ~DoubleLink();
 30 
 31         int getSize();
 32         int isEmpty();
 33 
 34         T get(int index);
 35         T getFirst();
 36         T getLast();
 37 
 38         int insert(int index, T t);
 39         int insertFirst(T t);
 40         int appendLast(T t);
 41 
 42         int del(int index);
 43         int deleteFirst();
 44         int deleteLast();
 45 
 46     private:
 47         int count;
 48         DNode<T> *pHead;
 49     private:
 50         DNode<T> *getNode(int index);
 51 };
 52 
 53 template<class T>
 54 DoubleLink<T>::DoubleLink() : count(0)
 55 {
 56     pHead = new DNode<T>();
 57     pHead->prev = pHead->next = pHead;
 58     //count = 0;
 59 }
 60 
 61 template<class T>
 62 DoubleLink<T>::~DoubleLink()
 63 {
 64     DNode<T> *ptmp;
 65     DNode<T> *pnode = pHead->next;
 66     while(pnode != pHead)
 67     {
 68         ptmp = pnode;
 69         pnode = pnode->next;
 70         delete ptmp;
 71     }
 72 
 73     delete pHead;
 74     pHead = NULL;
 75 }
 76 
 77 template<class T>
 78 int DoubleLink<T>::getSize()
 79 {
 80     return count;
 81 }
 82 
 83 template<class T>
 84 int DoubleLink<T>::isEmpty()
 85 {
 86     return count == 0;
 87 }
 88 
 89 template<class T>
 90 DNode<T> *DoubleLink<T>::getNode(int index)
 91 {
 92     if(index < 0 || index >= count)
 93     {
 94         cout << "Get node failed! The index in out of bound!" << endl;
 95         return NULL;
 96     }
 97 
 98     if(index <= count/2)
 99     {
100         int i = 0;
101         DNode<T> *pindex = pHead->next;
102         while(i++ < index)
103         {
104             pindex = pindex->next;
105         }
106 
107         return pindex;
108     }
109 
110     int j = 0;
111     int lindex = count - index -1;
112     DNode<T> *prindex = pHead->prev;
113     while(j++ < lindex)
114     {
115         prindex = prindex->prev;
116     }
117 
118     return prindex;
119 }
120 
121 template<class T>
122 T DoubleLink<T>::get(int index)
123 {
124     return getNode(index)->value;
125 }
126 
127 template<class T>
128 T DoubleLink<T>::getFirst()
129 {
130     return getNode(0)->value;
131 }
132 
133 template<class T>
134 T DoubleLink<T>::getLast()
135 {
136     return getNode(count - 1)->value;
137 }
138 
139 template<class T>
140 int DoubleLink<T>::insert(int index, T t)
141 {
142     if(index == 0)
143     {
144         return insertFirst(t);
145     }
146 
147     DNode<T> *pindex = getNode(index);
148     DNode<T> *pnode  = new DNode<T>(t, pindex->prev, pindex);
149     pindex->prev->next = pnode;
150     pindex->prev = pnode;
151     count++;
152 
153     return 0;
154 }
155 
156 template<class T>
157 int DoubleLink<T>::insertFirst(T t)
158 {
159     DNode<T> *pnode   = new DNode<T>(t, pHead, pHead->next);
160     pHead->next->prev = pnode;
161     pHead->next = pnode;
162     count++;
163 
164     return 0;
165 }
166 
167 template<class T>
168 int DoubleLink<T>::appendLast(T t)
169 {
170     DNode<T> *pnode   = new DNode<T>(t, pHead->prev, pHead);
171     pHead->prev->next = pnode;
172     pHead->prev = pnode;
173     count++;
174 
175     return 0;
176 }
177 
178 template<class T>
179 int DoubleLink<T>::del(int index)
180 {
181     DNode<T> *pindex   = getNode(index);
182     pindex->next->prev = pindex->prev;
183     pindex->prev->next = pindex->next;
184     delete pindex;
185     count--;
186 
187     return 0;
188 }
189 
190 template<class T>
191 int DoubleLink<T>::deleteFirst()
192 {
193     DNode<T> *temp = pHead;
194     pHead->next->prev = pHead->prev;
195     pHead->prev->next = pHead->next;
196     pHead = pHead->next;
197     count--;
198     delete temp;
199 
200     return 0;
201 }
202 
203 template<class T>
204 int DoubleLink<T>::deleteLast()
205 {
206     return del(count-1);
207 }
208 
209 #endif
View Code

测试代码如下:

  1 #include <iostream>
  2 #include <string>
  3 #include "DoubleLink.h"
  4 #include "SingleLink.h"
  5 using namespace std;
  6 
  7 void IntTest()
  8 {
  9     cout << "\n----IntTest----" << endl;
 10 
 11     DoubleLink<int> *pdlink = new DoubleLink<int>();
 12 
 13     pdlink->insert(0, 20);
 14     pdlink->appendLast(10);
 15     pdlink->insertFirst(30);
 16 
 17     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 18 
 19     cout << "size() = " << pdlink->getSize() << endl;
 20 
 21     int sz = pdlink->getSize();
 22     for(int i = 0; i < sz; i++)
 23     {
 24         cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
 25     }
 26 
 27     delete pdlink;
 28 }
 29 
 30 void StringTest()
 31 {
 32     cout << "\n----StringTest----" << endl;
 33 
 34     string sarr[3] = {"ten", "twenty", "thirty"};
 35 
 36     DoubleLink<string> *pdlink = new DoubleLink<string>();
 37 
 38     pdlink->insert(0, sarr[0]);
 39     pdlink->appendLast(sarr[1]);
 40     pdlink->insertFirst(sarr[2]);
 41 
 42     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 43 
 44     cout << "size() = " << pdlink->getSize() << endl;
 45 
 46     int sz = pdlink->getSize();
 47     for(int i = 0; i < sz; i++)
 48     {
 49         cout << "pdlink(" << i << ") = " << pdlink->get(i) <<endl;
 50     }
 51 
 52     delete pdlink;
 53 }
 54 
 55 struct stu
 56 {
 57     int id;
 58     char name[20];
 59 };
 60 
 61 static stu arr_stu[] =
 62 {
 63     {10, "sky"},
 64     {20, "jody"},
 65     {30, "vic"},
 66 };
 67 
 68 void ObjectTest()
 69 {
 70     cout << "\n----ObjectTest----" << endl;
 71 
 72     DoubleLink<stu> *pdlink = new DoubleLink<stu>();
 73 
 74     pdlink->insert(0, arr_stu[0]);
 75     pdlink->appendLast(arr_stu[1]);
 76     pdlink->insertFirst(arr_stu[2]);
 77 
 78     cout << "isEmpty() = " << pdlink->isEmpty() << endl;
 79 
 80     cout << "size() = " << pdlink->getSize() << endl;
 81 
 82     int sz = pdlink->getSize();
 83     struct stu p;
 84     for(int i = 0; i < sz; i++)
 85     {
 86         p = pdlink->get(i);
 87         cout << "pdlink(" << i << ") = [" << p.id << ", " << p.name << "]" << endl;
 88     }
 89 
 90     delete pdlink;
 91 }
 92 
 93 int main()
 94 {
 95     IntTest();
 96     StringTest();
 97     ObjectTest();
 98 
 99     return 0;
100 }
View Code

两种链表的测试结果相同,都为:

----IntTest----
isEmpty() = 0
size() = 3
pdlink(0) = 30
pdlink(1) = 20
pdlink(2) = 10

----StringTest----
isEmpty() = 0
size() = 3
pdlink(0) = thirty
pdlink(1) = ten
pdlink(2) = twenty

----ObjectTest----
isEmpty() = 0
size() = 3
pdlink(0) = [30, vic]
pdlink(1) = [10, sky]
pdlink(2) = [20, jody]

三、单向链表的逆序

1、循环逆序

代码如下:

 1 #include <iostream>
 2 #include <string>
 3 #include "DoubleLink.h"
 4 #include "SingleLink.h"
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     cout << "\n----ReverseTest----" << endl;
10 
11     SingleLink<int> *pdlink = new SingleLink<int>();
12 
13     pdlink->insert(0, 1);
14     pdlink->insert(0, 2);
15     pdlink->insert(0, 3);
16     pdlink->insert(0, 4);
17     pdlink->insert(0, 5);
18 
19     cout << "\n----Before reverse----" << endl;
20     cout << "size() = " << pdlink->getSize() << endl;
21     int sz = pdlink->getSize();
22     for(int i = 0; i < sz; i++)
23     {
24         cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
25     }
26 
27      SNode<int> *current = pdlink->getHeadNode();
28      SNode<int> *next = NULL, *result = NULL;
29      while(current != NULL)
30      {
31          next = current->next;
32          current->next = result;
33          result = current;
34          current = next;
35      }
36      pdlink->setHeadNode(result);
37 
38      cout << "\n----After reverse----" << endl;
39      for(int i = 0; i < sz; i++)
40      {
41          cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
42      }
43 
44      delete pdlink;
45 
46      return 0;
47 }
View Code

根据上面代码的思路,下图以1——>2——>3——>NULL这个链表为例,用图示来说明逆序的过程:

2、递归逆序

代码如下:

 1 #include <iostream>
 2 #include <string>
 3 #include "DoubleLink.h"
 4 #include "SingleLink.h"
 5 using namespace std;
 6 
 7 template<class T>
 8 SNode<T> *ReverseSingleLink(SNode<T> *phead)
 9 {
10     SNode<T> *newHead;
11     if(phead->next == NULL) return phead;
12     newHead = ReverseSingleLink(phead->next);
13 
14     phead->next->next = phead;
15     phead->next = NULL;
16 
17     return newHead;
18 }
19 
20 int main()
21 {
22     cout << "\n----ReverseTest----" << endl;
23 
24     SingleLink<int> *pdlink = new SingleLink<int>();
25 
26     pdlink->insert(0, 1);
27     pdlink->insert(0, 2);
28     pdlink->insert(0, 3);
29     pdlink->insert(0, 4);
30     pdlink->insert(0, 5);
31 
32     cout << "\n----Before reverse----" << endl;
33     cout << "size() = " << pdlink->getSize() << endl;
34     int sz = pdlink->getSize();
35     for(int i = 0; i < sz; i++)
36     {
37         cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
38     }
39 
40     pdlink->setHeadNode(ReverseSingleLink(pdlink->getHeadNode()));
41     cout << "\n----After reverse----" << endl;
42     cout << "size() = " << pdlink->getSize() << endl;
43     for(int i = 0; i < sz; i++)
44     {
45         cout << "pdlink(" << i << ") = " << pdlink->get(i) << endl;
46     }
47 
48     delete pdlink;
49 
50     return 0;
51 }
View Code

两种逆序算法的结果都为:

----ReverseTest----

----Before reverse----
size() = 5
pdlink(0) = 5
pdlink(1) = 4
pdlink(2) = 3
pdlink(3) = 2
pdlink(4) = 1

----After reverse----
size() = 5
pdlink(0) = 1
pdlink(1) = 2
pdlink(2) = 3
pdlink(3) = 4
pdlink(4) = 5
posted @ 2017-10-23 17:47  洗盏更酌  Views(948)  Comments(0Edit  收藏  举报