C++ 循环双链表(带头结点)
作者:互联网
文章目录
总结归纳
- 在 InsertPriorNode 函数(前插操作)中,如果想在表尾处插入结点,则无法进行,需要特殊处理,比较简单,这里没有写出;同时,也可以使用 InsertNextNode 函数(后插操作)来实现。
- 循环双链表的实现与循环单链表大同小异,甚至还更为简洁。由于可以快速找到指定结点的前驱结点,所以很多对头结点、尾节点的插入和删除操作就不用特殊处理。
- 当然,循环双链表要付出一定的内存代价。
代码实现
/*
循环双链表(带头结点)
*/
#include <iostream>
#include <string>
using namespace std;
struct DNode {
int data; // 数据域
DNode *prior; // 前驱结点
DNode *next; // 后继结点
};
typedef DNode DNode; // DNode是一个循环双链表的结点
typedef DNode *DLinkList; // LinkList是一个循环双链表
// 初始化循环双链表
void InitList(DLinkList &L) {
L = new DNode;
// L = (DNode *)malloc(sizeof(DNode));
L->next = L;
L->prior = L;
}
// 判断循环双链表是否为空
bool Empty(DLinkList &L) {
if (L->next == L) {
return true;
} else {
return false;
}
}
// 获取循环双链表长度
int GetLength(DLinkList &L) {
DNode *p = L->next;
int length = 0;
while (p != L) {
p = p->next;
length++;
}
return length;
}
// 头插法建立循环双链表
DLinkList DList_HeadInsert(DLinkList &L) {
int e;
cin >> e;
while (e != 9999) {
if (L->next == L) { // 第一次插入时要特殊处理
DNode *s = new DNode;
s->data = e;
s->next = L->next;
L->next = s;
s->prior = L;
L->prior = s;
cin >> e;
} else {
DNode *s = new DNode;
s->data = e;
s->next = L->next;
L->next->prior = s;
L->next = s;
s->prior = L;
cin >> e;
}
}
return L;
}
// 尾插法建立循环双链表
DLinkList DList_TailInsert(DLinkList &L) {
DNode *r = L; // r为尾指针
int e;
cin >> e;
while (e != 9999) {
DNode *s = new DNode;
s->next = r->next;
s->prior = r;
s->data = e;
r->next = s;
L->prior = s;
r = s; // 更新尾指针
cin >> e;
}
return L;
}
// 按位查找:查找第i个结点
DNode *GetElem(DLinkList &L, int i) {
if (i < 0) {
return NULL;
}
DNode *p = L;
int j = 0;
while (p->next != L && j != i) {
p = p->next;
j++;
}
return p;
}
// 按值查找:查找数据域为e的结点
DNode *GetLNode(DLinkList &L, int e) {
DNode *p = L->next;
while (p != L && p->data != e) {
p = p->next;
}
return p;
}
// 前插操作:在p结点前插入数据e
bool InsertPriorNode(DLinkList &L, DNode *p, int e) {
if (p == L) { // 在头结点前插入
return false;
}
DNode *s = new DNode;
s->next = p;
s->prior = p->prior;
s->data = e;
p->prior->next = s;
p->prior = s;
return true;
}
// 后插操作:在p结点后插入数据e
bool InsertNextNode(DLinkList &L, DNode *p, int e) {
if (p == L) {
return false;
}
DNode *s = new DNode;
s->next = p->next;
p->next->prior = s;
s->data = e;
p->next = s;
s->prior = p;
return true;
}
// 按位序插入
bool DListInsert(DLinkList &L, int i, int e) {
if (i < 1) {
return false;
}
DNode *p = GetElem(L, i - 1); // 找到前一个结点
InsertNextNode(L, p, e); // 后插法
/* // 前插法,实现同样效果
// DNode *p = GetElem(L, i);
// InsertPriorNode(L, p, e);
*/
return true;
}
// 删除p结点的后继结点
bool DeleteNextDNode(DLinkList &L, DNode *p) {
if (p->next == L) { // p是最后一个结点
return false;
}
DNode *s = new DNode;
s = p->next;
p->next = s->next;
s->next->prior = p;
delete s;
return true;
}
// 删除当前结点
bool DeleteNode(DLinkList &L, DNode *p) {
if (p == L) {
return false;
}
p->prior->next = p->next;
p->next->prior = p->prior;
delete p;
return true;
}
// 按位序删除
bool DListDelte(DLinkList &L, int i, int &e) {
if (i < 1) {
return false;
}
DNode *p = new DNode;
p = GetElem(L, i);
e = p->data;
DeleteNode(L, p); // 删除当前结点
/* // 删除前一个结点的后继结点,达到同样效果
DNode *p = new DNode;
p = GetElem(L, i - 1);
e = p->next->data;
DeleteNextDNode(L, p);
*/
return true;
}
// 遍历单链表
void TraverseDList(DLinkList &L) {
DNode *p = L->next;
while (p != L) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main() {
DLinkList L;
InitList(L);
cout << Empty(L) << endl;
// L = DList_HeadInsert(L); // 头插法
L = DList_TailInsert(L); // 尾插法
TraverseDList(L);
DListInsert(L, 3, 5244);
TraverseDList(L);
int e = -1;
DListDelte(L, 1, e);
cout << "被删除的值:" << e << endl;
TraverseDList(L);
cout << "尾节点:" << L->prior->data << endl; // 检查尾节点
cout << "头结点的后继结点:" << L->next->next->data << endl; // 检查头结点的后继结点
}
标签:结点,return,C++,next,prior,DLinkList,双链,DNode 来源: https://blog.51cto.com/u_15251606/2852397