程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 雙向鏈表(C++實現),實現

雙向鏈表(C++實現),實現

編輯:C++入門知識

雙向鏈表(C++實現),實現


wKioL1busLOTWsqhAAAI3EcuKqo751.png

////////////////////////////////////////////////////////////////////////////////////// /////// 這裡建立兩個類,一個節點類和一個List類,與單鏈表不同的是雙向鏈表的節點要多一 ////// 個前驅指針,相應的,雙向鏈表函數實現要與單鏈表實現有所差異 typedef int DataType; //struct LinkNode //節點類(復合形態) //{ // friend class SList; //將SList設為友元,便於SList類可以訪問節點類的私有成員 //public: // LinkNode(const DataType x); //private: // DataType _data; //節點的數據 // LinkNode* _next; //指向該節點的下一個節點 // LinkNode* _prev; //指向該節點的前一個節點 //}; //直接用struct定義LinkNode類,因為struct的成員默認為公有數據成員,所以可直接訪問 struct LinkNode //節點類(建議寫法) { LinkNode(const DataType x); DataType _data; //節點的數據 LinkNode* _next; //後繼指針 LinkNode* _prev; //前驅指針 }; class List //鏈表類 { public: List(); //構造函數 List(const List& s); //拷貝構造 List &operator=(List& s); //賦值運算符的重載 ~List(); public: void Reverse(); void Swap(List& s); void PrintSList(); //打印鏈表 void PushBack(const DataType& x); //在尾部插入一個節點 void Clear(); //鏈表置空 void PopBack(); void PushFront(DataType x); //頭插 void PopFront(); //刪除首節點 void Insert(LinkNode* pos, DataType x);//固定位置插入一個節點 void Erase(LinkNode* pos); //刪除某一節點 LinkNode* Find(DataType x); //查找節點並返回這個節點的地址 int Amount(); //計算鏈表節點的數目 void Remove(DataType x); //查找某節點並刪除 private: LinkNode* _head; //指向頭結點 LinkNode* _tail; //指向尾節點 }; List.h 1 #include<iostream> 2 using namespace std; 3 #include<assert.h> 4 #include"List.h" 5 6 //節點類構造函數* 7 LinkNode::LinkNode(const DataType x) 8 :_data(x) 9 , _next(NULL) 10 , _prev(NULL) 11 {} 12 13 //鏈表類* 14 List::List() //構造函數 15 : _head(NULL) 16 , _tail(NULL) 17 {} 18 19 List::List(const List& s) //拷貝構造 20 : _head(NULL) 21 , _tail(NULL) 22 { 23 if (s._head == NULL) 24 { 25 return; 26 } 27 LinkNode* tmp = s._head; 28 while (tmp) 29 { 30 PushBack(tmp->_data); 31 tmp = tmp->_next; 32 } 33 34 } 35 36 //賦值運算符的重載(傳統方法) 37 //SList & SList::operator=(const SList& s) 38 //{ 39 // if (this != &s) 40 // { 41 // _head = NULL; 42 // _tail = NULL; 43 // LinkNode* tmp = s._head; 44 // do{ 45 // PushBack(tmp->_data); 46 // tmp = tmp->_next; 47 // } while (tmp != s._head); 48 // } 49 // return *this; 50 //} 51 52 //賦值運算符的重載(高效寫法)* 53 /*void SList::Swap(SList& s) 54 { 55 swap(_head, s._head); 56 swap(_tail, s._tail); 57 58 } 59 SList& SList::operator=(SList &s) 60 { 61 if (this != &s) 62 { 63 SList tmp(s); 64 Swap(tmp); 65 } 66 return *this; 67 }*/ 68 69 List& List::operator=(List &s) //賦值運算符的重載再優化(推薦寫法) 70 { 71 if (this != &s) 72 { 73 swap(_head, s._head); 74 swap(_tail, s._tail); 75 } 76 return *this; 77 } 78 List::~List() //析構 79 { 80 Clear(); 81 } 82 83 void List::Reverse() //鏈表逆置(利用頭插新節點的方法) 84 { 85 if (_head == NULL || _head== _tail) 86 { 87 return; 88 } 89 int ret = Amount(); 90 91 /* // 方法一(相當於用頭插的方式重新建立鏈表) 92 _tail = new LinkNode(_head->_data); 93 LinkNode* begin = NULL; 94 LinkNode* tmp = _tail; 95 while (--ret) 96 { 97 LinkNode* del = _head; 98 _head = _head->_next; 99 delete del; 100 begin = new LinkNode(_head->_data); 101 begin->_next = tmp; 102 tmp->_prev = begin; 103 tmp = begin; 104 } 105 _head = begin;*/ 106 107 ////// 方法二(只是交換對稱位置節點的數據)**(高效) 108 LinkNode* begin = _head; 109 LinkNode* end = _tail; 110 while (ret) 111 { 112 if (end->_next == begin) 113 break; 114 ret /= 2; 115 swap(begin->_data, end->_data); 116 begin = begin->_next; 117 end = end->_prev; 118 } 119 120 /*// 方法三 交換前驅和後繼指針 121 swap(_head, _tail); 122 LinkNode* cur = _head; 123 while (cur) 124 { 125 swap(cur->_prev,cur->_next); 126 cur = cur->_next; 127 } 128 */ 129 130 } 131 132 //打印鏈表* 133 void List::PrintSList() 134 { 135 //頭結點為空時,無需打印鏈表 136 if (_head == NULL) 137 { 138 cout << "This SList is Empty !" << endl; 139 return; 140 } 141 else 142 { 143 LinkNode* tmp = _head; 144 while (tmp) 145 { 146 cout << tmp->_data << "-->"; 147 tmp = tmp->_next; 148 } 149 cout <<"NULL"<< endl; 150 } 151 } 152 153 void List::PushBack(const DataType& x) //在尾部插入一個節點* 154 { 155 //如果鏈表為空,插入節點後只有一個節點,此時_head=_tail 156 if (_head == NULL) 157 { 158 _head = new LinkNode(x); 159 _tail = _head; 160 } 161 else 162 { 163 _tail->_next = new LinkNode(x); 164 _tail->_next->_prev=_tail; 165 _tail = _tail->_next; 166 } 167 } 168 169 void List::Clear() //鏈表置空* 170 { 171 LinkNode* begin = _head; 172 while (begin != _tail) 173 { 174 _head = _head->_next; 175 delete begin; 176 begin = _head; 177 } 178 _head = NULL; 179 _tail = NULL; 180 } 181 182 void List::PopBack() //尾刪 183 { 184 if (_head == NULL) 185 { 186 cout << "This SList is empty !" << endl; 187 } 188 else if (_head == _tail) 189 { 190 delete _head; 191 _head = NULL; 192 _tail = NULL; 193 } 194 else 195 { 196 LinkNode* cur = _head; 197 while (cur->_next != _tail) 198 { 199 cur = cur->_next; 200 } 201 delete _tail; 202 _tail = cur; 203 _tail->_prev = cur->_prev; 204 _tail->_next = NULL; 205 } 206 } 207 208 void List::PushFront(DataType x) //頭插* 209 { 210 if (_head == NULL) 211 { 212 PushBack(x); 213 } 214 else 215 { 216 LinkNode* tmp = _head; 217 _head = new LinkNode(x); 218 _head->_next = tmp; 219 tmp->_prev = _head; 220 } 221 } 222 223 void List::PopFront() //刪除首節點 224 { 225 if (_head == NULL) 226 { 227 cout << "This SList is empty !" << endl; 228 return; 229 } 230 LinkNode* tmp = _head; 231 _head = _head->_next; 232 _head->_prev = NULL; 233 delete tmp; 234 } 235 236 //固定位置插入一個節點(這個函數需和Find函數搭配使用) 237 //先用Find函數找到新節點需要插入的位置 238 //(將Find函數的返回值傳給Insert函數的參數pos),再在pos節點後面插入新節點x 239 void List::Insert(LinkNode* pos, DataType x) //* 240 { 241 assert(pos); 242 if (pos == _tail) 243 { 244 PushBack(x); 245 } 246 else 247 { 248 LinkNode* tmp = new LinkNode(x); 249 tmp->_next = pos->_next; 250 pos->_next = tmp; 251 tmp->_next->_prev = tmp; 252 tmp->_prev = pos; 253 } 254 } 255 256 //刪除某一節點,同樣,要先找到該節點並傳參給Erase函數 257 void List::Erase(LinkNode* pos) 258 { 259 assert(pos); 260 if (pos == _tail) 261 { 262 PopBack(); 263 } 264 else if (pos == _head) 265 { 266 PopFront(); 267 } 268 else 269 { 270 pos->_prev->_next = pos->_next; 271 pos->_next->_prev = pos->_prev; 272 delete pos; 273 } 274 } 275 276 //查找節點並返回這個節點的地址 277 LinkNode* List::Find(DataType x) 278 { 279 if (_head == NULL) 280 { 281 cout << "This SList is empty !" << endl; 282 return NULL; 283 } 284 else 285 { 286 LinkNode* tmp = _head; 287 while (tmp != NULL) 288 { 289 if (tmp->_data == x) 290 { 291 return tmp; 292 } 293 tmp = tmp->_next; 294 } 295 return NULL; 296 } 297 } 298 299 int List::Amount() //計算鏈表節點的數目 300 { 301 if (_head == NULL) 302 { 303 return 0; 304 } 305 else 306 { 307 int count = 0; 308 LinkNode* cur = _head; 309 while (cur != _tail) 310 { 311 count++; 312 cur = cur->_next; 313 } 314 return ++count; 315 } 316 } 317 318 void List::Remove(DataType x) //查找某節點並刪除 319 { 320 if (_head == NULL) 321 { 322 cout << "This SList is empty !" << endl; 323 } 324 else 325 { 326 LinkNode* tmp = Find(x); 327 if (tmp != NULL) 328 { 329 Erase(tmp); 330 } 331 } 332 } List.cpp 1 #include"List.h" 2 #include<stdlib.h> 3 #include<iostream> 4 using namespace std; 5 6 void Test1() 7 { 8 List list1; 9 list1.PushBack(1); 10 list1.PushBack(2); 11 list1.PushBack(3); 12 list1.PushBack(4); 13 list1.PushBack(5); 14 list1.PushBack(6); 15 list1.PrintSList(); 16 17 /* List list2(list1); 18 list2.PrintSList();*/ 19 20 List list2=list1; 21 list2.PrintSList(); 22 //list2.PopBack(); 23 //list2.Clear(); 24 //list2.PushFront(0); 25 //list2.PopFront(); 26 27 //////檢驗Find函數 28 ////LinkNode* ret=list2.Find(4); 29 ////if (ret != NULL) 30 ////{ 31 //// cout << "ret:" << ret << " " << ret->_data << endl; 32 ////} 33 ////else 34 ////{ 35 //// cout << "Not exit !" << endl; 36 ////} 37 38 /* int ret=list2.Amount(); 39 cout << ret << endl;*/ 40 41 //list2.Erase(list2.Find(5)); 42 //list2.Insert(list2.Find(2), 0); 43 //list2.Remove(3); 44 list2.Reverse(); 45 list2.PrintSList(); 46 } 47 48 int main() 49 { 50 Test1(); 51 system("pause"); 52 } Test.cpp

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved