参考博客:数组、单链表和双链表介绍 以及 双向链表的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
测试代码如下:
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 << " ----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 << " ----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 << " ----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 }
二、双链表
双链表的结构如下:
本文的实现中,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
测试代码如下:
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 << " ----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 << " ----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 << " ----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 }
两种链表的测试结果相同,都为:
----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 << " ----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 << " ----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 << " ----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 }
根据上面代码的思路,下图以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 << " ----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 << " ----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 << " ----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 }
两种逆序算法的结果都为:
----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