【C++資料結構】模版類實現雙迴圈連結串列的基本操作
阿新 • • 發佈:2019-02-08
單鏈表結構為我們提供方便分資料插入和刪除工作,美中不足的是查詢資料不方便,對於單鏈表查詢資料至少要遍歷一邊. 為此我們提出雙鏈表結構,從而方便的查詢資料.
給出雙鏈表的一般結構:
一種是帶頭結點(哨兵位)的管理方式,另一種是帶管理節點管理方式。 但是我們不建議採用管理節點和頭結點並存的方式(管理較前兩者複雜)。
提供帶頭結點的雙迴圈連結串列模版類實現,程式碼如下:
標頭檔案:
#pragma once #include<iostream> using namespace std; template<class _T> class DCList { protected: struct Node; friend struct Node; typedef _T* _ptr; typedef Node* _NodePtr; struct Node { _NodePtr _Prev; _NodePtr _Next; _T _Value; }; private: size_t Size; _NodePtr Handle; public: DCList() :Size(0), Handle(_BuyNode()) {} ~DCList() { clear(); _FreeNode(Handle); Size = 0; } public: bool IsEmpty() { return Size == 0; } size_t length() { return Size; } _NodePtr& begin() { return Handle->_Next; } _NodePtr& end() { return Handle; } void Insert(_NodePtr _P, const _T& v) { _NodePtr _S = _BuyNode(_P, _P->_Prev); _P->_Prev = _S; _S->_Prev->_Next = _S; _S->_Value = v; ++Size; } bool Insert_val(const _T& x) { _NodePtr _P = _BuyNode(NULL,NULL,x); Insert_val(_P); return true; } void Insert(_NodePtr _P, _NodePtr _S) { _S->_Next = _P->_Next; _P->_Next->_Prev = _S; _P->_Next = _S; _S->_Prev = _P; if (_P == Handle->_Prev) { _S->_Next = Handle; Handle->_Prev = _S; } Size++; } void Insert_val(_NodePtr _Cur) { _NodePtr _P = Handle; while (_P->_Next != end() && _Cur->_Value > _P->_Next->_Value) _P = _P->_Next; Insert(_P, _Cur); } void push_back(const _T& x) { Insert(end(), x); } void push_front(const _T& x) { Insert(begin(), x); } void ShowList() { if (IsEmpty()) { cout << "null" << endl; return; } _NodePtr cur = begin(); while (cur != end()) { cout << cur->_Value << "->"; cur = cur->_Next; } cout << "null" << endl; } void erase(_NodePtr _P) //刪除自己 { if (IsEmpty()) return; if ( _P != Handle && _P != NULL) { _P->_Prev->_Next = _P->_Next; _P->_Next->_Prev = _P->_Prev; _P->_Prev = _P->_Next = NULL; } Size--; _FreeNode(_P); } void pop_back() { erase(Handle->_Prev); } void pop_front() { erase(Handle->_Next); } _NodePtr& find(const _T v) { _NodePtr _Cur = begin(); while (_Cur != end()) { if (_Cur->_Value == v) return _Cur; } cout << "無此節點,返回頭" << endl; return Handle; } void delete_value(const _T _V) { _NodePtr p; while (p = find(_V), p != end()) { erase(p); } } _T& findBypos(size_t pos) { if (pos > Size) { cout << "多走 "<< pos/Size<<"圈" << endl; pos %= Size; } _NodePtr p = begin(); while (p !=end() && pos-1) { p = p->_Next; pos--; } return p->_Value; } void clear() { while (!IsEmpty()) pop_front(); } void destroy() { clear(); _FreeNode(Handle); Handle = NULL; } void merge(DCList& r) { _NodePtr p = r.begin(); _NodePtr q; r.Handle->_Next = NULL; p->_Prev = NULL; while (p->_Next !=NULL) { q = p; p = p->_Next; q->_Next = NULL; p->_Prev = NULL; Insert_val(q); r.Size--; } r.begin() = r.end(); } void sort() { if (length() <= 1) return; _NodePtr _P = begin()->_Next; _NodePtr _Q; begin()->_Next->_Prev = NULL; begin()->_Next = Handle; Handle->_Prev = begin(); Size = 1; while (_P != end()) { _Q = _P; _P = _P->_Next; _Q->_Next = NULL; _P->_Prev = NULL; Insert_val(_Q); } } void resver() { if (length() <= 1) return; _NodePtr _P = begin()->_Next; _NodePtr _Q; begin()->_Next->_Prev = NULL; begin()->_Next = Handle; Handle->_Prev = begin(); Size = 1; while (_P != end()) { _Q = _P; _P = _P->_Next; _Q->_Next = NULL; _P->_Prev = NULL; begin()->_Prev = _Q; _Q->_Next = begin(); Handle->_Next = _Q; _Q->_Prev = Handle; } } protected: _NodePtr _BuyNode(_NodePtr _Narg = NULL, _NodePtr _Parg = NULL, _T v = 0) { _NodePtr _S = new Node; _S->_Next = _Narg != 0 ? _Narg : _S; _S->_Prev = _Parg != 0 ? _Parg : _S; _S->_Value = v; return (_S); } void _FreeNode(_NodePtr _P) { delete _P; _P = NULL; } };
測試程式碼:
#include<iostream> #include "DCList.h" using namespace std; void main() { DCList<int> mylist; size_t select = 1; int item = 0; size_t pos = 0; while (select) { cout << "************************************" << endl; cout << "* [0] quit_system [1] push_back *" << endl; cout << "* [2] push_front [3] show_seqlist*" << endl; cout << "* [4] pop_back [5] pop_front *" << endl; cout << "* [6] insert_val [7] delete_val *" << endl; cout << "* [8] find [9] merge *" << endl; cout << "* [10] sort [11] clear *" << endl; cout << "* [12] destroy [13] length *" << endl; cout << "* [14] resver [15] next *" << endl; cout << "* [16] prio *" << endl; cout << "************************************" << endl; cout << "請選擇:>"; cin >> select; system("cls"); switch (select) { case 1: cout << "請輸入要插入的資料(-1結束):>"; while (cin >> item, item != -1) { mylist.push_back(item); } break; case 2: cout << "請輸入要插入的資料(-1結束):>"; while (cin >> item, item != -1) { mylist.push_front(item); } break; case 3: mylist.ShowList(); break; case 4: mylist.pop_back(); break; case 5: mylist.pop_front(); break; case 6: cout << "請輸入要插入的數:> " << endl; cin >> item; mylist.Insert_val(item); break; case 7: //error cout << "請輸入要刪除的數:> " << endl; cin >> item; mylist.delete_value(item); break; case 8: cout << "請輸入要查詢的位置:> " << endl; cin >> pos; cout << mylist.findBypos(pos) << endl; break; case 11: cout << "連結串列將被清空:> " << endl; mylist.clear(); break; case 12: cout << "連結串列將被摧毀:> " << endl; mylist.destroy(); break; case 13: cout<<"長度為:> "<<mylist.length()<<endl; break; case 14: cout << "連結串列將被逆置 ! " << endl; // mylist.resver(); mylist.ShowList(); break; default: break; } } }
函式的呼叫與引用關係如下:
執行環境:VS2015