數據結構--C++雙鏈表

雙鏈表的實現與單鏈表其實差不太多,只不過在雙鏈表中,除了首尾結點,每個結點都有一個前驅和一個後繼結點,本篇只談論簡單的實現雙鏈表的基本功能,回了之後其實在向別的地方拓展也很容易了。

//created by kong 2020-03-29
#include<iostream>
using namespace std;

template <typename T>
struct DLinkList{          //雙鏈表結點類型
	T data;				   //存放數據元素	
	DLinkList<T>* prior;   //指向前一個結點的域
	DLinkList<T>* next;	   //指向下一個結點的域
};

template<typename T>
class DLinkListClass{			//雙鏈表類模板
	DLinkList<T>* dhead;		//雙鏈表頭結點指針
public:
	DLinkListClass<T>();			//構造函數,構建一個空的雙鏈表
	~DLinkListClass<T>();			//析構函數,銷燬雙鏈表
	void CreateListF(T a[], int n); //採用頭插法建立雙鏈表
	void CreateListR(T a[], int n); //採用尾插法建立雙鏈表
	void DispList();				//輸出雙鏈表的所有結點值
	int ListLength();				//求出雙鏈表中結點個數
	int GetElem(int i);		        //求雙鏈表中某個數據元素值
	int LocateElem(T e);			//按元素查找
	bool ListInsert(int i, T e);	//插入數據元素
	bool ListDelete(int i);			//刪除數據元素
};

template<typename T>
void DLinkListClass<T>::CreateListF(T a[], int n) {     //採用頭插法建立數據結點
	DLinkList<T>* s;
	int i;
	for(i=0;i<n;i++){			  //循環建立數據結點
		s = new DLinkList<T>();
		s->data = a[i];           //創建數據結點*s
		s->next = dhead->next;    //將*s插入到開始結點之前、頭結點之後
		if (dhead->next != NULL)
			dhead->next->prior = s;
		dhead->next = s;
		s->prior = dhead;
	}
}

template<typename T>
void DLinkListClass<T>::CreateListR(T a[],int n){      //採用尾插法建立雙鏈表
	DLinkList<T>* s, * r;
	int i;
	r = dhead;					 //r始終指向尾結點,開始時指向頭結點
	for(i=0;i<n;i++){            //循環建立數據結點
		s = new DLinkList<T>();
		s->data = a[i];          //創建數據結點*s
		r->next = s;			 //將*s結點插入到r結點之後
		s->prior = r;
		r = s;
	}
	r->next = NULL;
}

template<typename T>
DLinkListClass<T>::DLinkListClass<T>() {   //構造函數,創建一個空的雙鏈表
	dhead = new DLinkList<T>();
	dhead->next = NULL;
}

template<typename T>
DLinkListClass<T>::~DLinkListClass<T>() {	//析構函數,銷燬雙鏈表
	DLinkList<T>* pre, * p;
	pre = dhead; p = pre->next;              //pre指向頭結點,p指向其後繼結點
	while (p != NULL) {
		delete pre;                         //釋放前一個結點
		pre = p; p = p->next;               //pre、p同步後移
	}
	delete pre;								//當p=NULL時,pre指向尾結點,且需要釋放尾結點
	cout << "LinkList Destructing..." << endl;
}

template<typename T>
void DLinkListClass<T>::DispList() {        //輸出鏈表所有結點值
	DLinkList<T>* p;
	p = dhead->next;						//p指向開始結點
	cout << "鏈表元素爲:";
	while (p != NULL) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

template<typename T>
int DLinkListClass<T>::ListLength() {    //求雙鏈表中數據結點個數
	int i = 0; DLinkList<T>* p;
	p = dhead;
	while (p->next != NULL) {
		i++;
		p = p->next;
	}
	return (i);							//循環結束,p指向尾結點,序號i爲結點個數
}

template<typename T>
int DLinkListClass<T>::GetElem(int i) {//求單鏈表中某個數據元素值
	int j = 0;
	DLinkList<T>* p;
	p = dhead;       //p指向頭結點,j置爲0
	while (j < i && p != NULL) {
		j++;
		p = p->next;
	}
	if (p == NULL)           //不存在這個結點,返回false
		return false;
	else {                   //存在,返回結點元素值
		return  p->data;
	}
}

template<typename T>
int DLinkListClass<T>::LocateElem(T e) {    //按元素查找
	int i = 1;
	DLinkList<T>* p;
	p = dhead->next;                     //p指向開始結點,i置爲1
	while (p != NULL && p->data != e) {    //查找data值爲e的結點*p,序號爲i
		p = p->next;
		i++;
	}
	if (p == NULL)
		return 0;        //不存在返回0
	else
		return i;        //存在返回其邏輯序號i
}

template<typename T>
bool DLinkListClass<T>::ListInsert(int i,T e){    //插入數據元素
	int j = 0;
	DLinkList<T>* s, * p = dhead;        //p指向頭結點,j設置爲0
	while(j<i-1&&p!=NULL){               //查找第i-1個結果
		j++;
		p = p->next;
	}
	if (p == NULL) return false;         //未找到第i-1個結點,返回false
	else {								 //找到第i-1個結點*p,在其後插入新結點*s
		s = new DLinkList<T>();			 
		s->data = e;                     //創建新結點*s
		s->next = p->next;               //在*p後插入*s結點
		if (p->next != NULL)
			p->next->prior = s;
		s->prior = p;
		p->next = s;
		return true;
	}
}

template<typename T>
bool DLinkListClass<T>::ListDelete(int i){        //刪除數據元素
	int j = 0;							//p指向頭結點,j設置爲0
	DLinkList<T>* p = dhead, * q;
	while(j<i-1&&p!=NULL){				//查找第i-1個結點
		j++;
		p = p->next;
	}
	if (p == NULL) return false;        //未找到第i-1個結點
	else{								//找到第i-1個結點
		q = p->next;					//q指向第i個結點
		if (q == NULL) return false;	//當不存在第i個結點時返回false
		p->next = q->next;				//從雙鏈表中刪除*q結點
		if (p->next != NULL)			//若*p結點存在後繼結點,修改其前驅元素
			p->next->prior = p;			
		delete q;						//釋放*q結點
		return true;
	}		
}

int main() {
	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	DLinkListClass<int> l1;
	l1.CreateListF(a, 10); l1.DispList();
	l1.CreateListR(a, 10);l1.DispList();
	cout << l1.ListLength() << endl;
	cout << l1.GetElem(5) << endl;
	cout << l1.LocateElem(7) << endl;
	l1.ListInsert(3, 11); l1.DispList();
	l1.ListDelete(7); l1.DispList();

	return 0;
}

運行結果:

當你熟練掌握了C++的基本語法後,其實學習數據結構是很簡單的,一定要自己多寫,加油!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章