双链表的实现与单链表其实差不太多,只不过在双链表中,除了首尾结点,每个结点都有一个前驱和一个后继结点,本篇只谈论简单的实现双链表的基本功能,回了之后其实在向别的地方拓展也很容易了。
//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++的基本语法后,其实学习数据结构是很简单的,一定要自己多写,加油!!