自己動手實現資料結構模板(1):雙向連結串列
阿新 • • 發佈:2018-12-13
今天忽然心血來潮,自己動手實現了一個簡單的雙向連結串列和基本功能,大致實現瞭如下功能
dtsListNode為結點類,包括值value、前向指標pre和後向指標next。
dtsList為雙向連結串列,能夠通過begin和end函式獲得首地址指標和指向最後一個元素之後一個的尾指標,使用empty函式判斷是否為空,size返回資料結點個數,print和print_rev輸出當前所有結點,以及使用add2Head、add2End、deleteFromHead、deleteFromEnd從首尾增加或刪除結點,並能夠在刪除結點或析構時及時釋放佔用的記憶體。
以下為原始碼:
#ifndef DTS_LIST_HPP #define DTS_LIST_HPP #include using namespace std; template class dtsListNode{ public: T value; dtsListNode* next; dtsListNode* pre; dtsListNode(T v,dtsListNode* nextPointer=NULL,dtsListNode* prePointer=NULL) :value(v),next(nextPointer),pre(prePointer){} dtsListNode():next(NULL),pre(NULL){} }; template class dtsList{ protected: dtsListNode* pHead;//空的頭結點 dtsListNode* pBegin;//連結串列第一個資料結點 dtsListNode* pTail;//連結串列最後一個數據結點 dtsListNode* pEnd;//空的尾結點 inline dtsListNode* insertAfter(dtsListNode* first,T val){ dtsListNode* second = new dtsListNode(val); dtsListNode* third = first->next; if(first==pHead) pBegin=second; if(first==pTail) pTail=second; first->next=second; second->pre=first; second->next=third; third->pre=second; return second; } inline T deleteAfter(dtsListNode* first){ T ret; if(!first || !first->next || !first->next->next) return ret; dtsListNode* second=first->next; dtsListNode* third=second->next; ret=second->value; if(first==pHead){//刪除結點為pBegin時 pBegin=third; } if(second==pTail){//刪除結點為pTail時 if(first!=pHead){ pTail=first; } else {//刪除最後一個結點時 pBegin=NULL; pTail=NULL; } } delete second; first->next=third; third->pre=first; return ret; } public: dtsList(){ pHead = new dtsListNode(); pEnd = new dtsListNode(); pBegin = NULL; pTail = NULL; pHead->next=pEnd; pEnd->pre=pHead; } inline bool empty(){ return pBegin==NULL; } int size(){ if(empty()) return 0; int ret=0; for(dtsListNode* it=pBegin;it!=pEnd;it=it->next){ ++ret; } return ret; } dtsListNode* begin(){ return pBegin; } dtsListNode* end(){ return pEnd(); } dtsList& add2End(T val){ if(!pTail || !pBegin){//當前無資料時 pBegin=insertAfter(pHead,val); pTail=pBegin; //print(); } else {//已有至少一個數據結點,將它加在最後 insertAfter(pTail,val); //print(); } //cout<<"node "<<val<<" added"<<endl; return *this; } dtsList& add2Head(T val){ if(!pBegin || !pTail){//當前無資料時 pBegin=insertAfter(pHead,val); pTail=pBegin; //print(); } else {//已有至少一個數據結點,將它加在最前面 insertAfter(pHead,val);//新的第一個資料結點 //print(); } //cout<<"node "<<val<<" added"<<endl; return *this; } T deleteFromEnd(){ if(pTail){ return deleteAfter(pTail->pre); } T ret; return ret; } T deleteFromHead(){ return deleteAfter(pHead); } void print(const char* separator="->",const char* null_str="空連結串列"){ if(pHead->next==pEnd){ cout<<null_str<<endl; return; } for( dtsListNode* it=pBegin;it!=pEnd;it=it->next ){ cout<value; if(it!=pEnd->pre) cout<<separator; } cout<<endl; } void print_rev(const char* separator="<-",const char* null_str="空連結串列"){ if(pHead->next==pEnd){ cout<<null_str<<endl; return; } for( dtsListNode* it=pTail;it!=pHead;it=it->pre ){ cout<value; if(it!=pHead->next) cout<<separator; } cout<<endl; } virtual ~dtsList(){ dtsListNode* node2Delete=pHead; dtsListNode* nextNode2Delete; while(node2Delete){ nextNode2Delete=node2Delete->next; //cout<<"node "<value<<" deleted."<<endl; delete node2Delete; node2Delete=nextNode2Delete; } //cout<<"list freed"<<endl; } }; #endif // !DTS_LIST_HPP
以下為測試主函式
#include<iostream> #include<string> #include"dtsList.hpp" using namespace std; int main(){ dtsList<string> l; l.add2Head("one"); l.add2End("two"); l.add2End("three"); l.add2Head("zero"); l.print("->"); l.print_rev(); cout<<"size:"<<l.size()<<endl; cout<<l.deleteFromEnd()<<" 被刪除"<<endl; l.print("->"); cout<<"size:"<<l.size()<<endl; cout<<l.deleteFromHead()<<" 被刪除"<<endl; l.print("->"); cout<<"size:"<<l.size()<<endl; cout<<l.deleteFromHead()<<" 被刪除"<<endl; l.print("->"); cout<<"size:"<<l.size()<<endl; cout<<l.deleteFromHead()<<" 被刪除"<<endl; l.print("->"); cout<<"size:"<<l.size()<<endl; }
輸出:
zero->one->two->three
three<-two<-one<-zero
size:4
three 被刪除 zero->one->two
size:3
zero 被刪除
one->two
size:2
one 被刪除
two
size:1
two 被刪除
空連結串列
size:0
按任意鍵繼續