雙鏈表的實現與單鏈表其實差不太多,只不過在雙鏈表中,除了首尾結點,每個結點都有一個前驅和一個後繼結點,本篇只談論簡單的實現雙鏈表的基本功能,回了之後其實在向別的地方拓展也很容易了。
//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++的基本語法後,其實學習數據結構是很簡單的,一定要自己多寫,加油!!