1. 程式人生 > >自己動手實現資料結構模板(1):雙向連結串列

自己動手實現資料結構模板(1):雙向連結串列

今天忽然心血來潮,自己動手實現了一個簡單的雙向連結串列和基本功能,大致實現瞭如下功能

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

按任意鍵繼續