#include<iostream>
using namespace std;
/*
循环链表:将单链表的终端节点的指针端由空指针改为指向头节点,即头尾相接
双向循环链表:每个节点保存指向前驱节点的指针
两个表:
head->A->B->C->D->E->F->head
head->a->b->c->d->e->f->head
合成为一个循环链表的思路:
1、将尾指针指向第二个链表的首节点
2、将第二个链表的尾节点指向第一个链表的头节点
3、释放第二个链表的头节点
*/
//双向链表节点结构体的表示
typedef struct DoubleNode
{
int date;
DoubleNode *prev;
DoubleNode *next;
}DoubleNode, *Linklist;
//双向链表的创建(不循环)
Linklist CreateList(Linklist &head, int n)
{
//链表初始化
head = new DoubleNode;
head->next = nullptr; //带头节点的空链表表示,前后指针置空
head->prev = nullptr;
head->date = 0;
Linklist p = nullptr;
//头插法-逆序插入
for(int i = 0; i < n; ++i)
{
p = new DoubleNode;
p->date = i * 2;
//头插法对于第一个节点的插入与后面节点的插入方法不同,因此要区别对待
if (head->next == nullptr)
{
p->next = head->next;
head->next = p;
p->prev = head;
}
else
{
p->next = head->next;
head->next->prev = p;
p->prev = head;
head->next = p;
}
}
return head;
}
//获取链表节点个数
int GetNums(Linklist head)
{
Linklist p = head->next;
int nums = 0;
while (p != nullptr)
{
p = p->next;
++nums;
}
return nums;
}
//双向链表的插入--在head链表的第n个位置插入date为value的节点
Linklist InsertList(Linklist head, int n, int value)
{
//判断n是否合法输入
if (GetNums(head))
{
if (n < 0 || n > GetNums(head) + 1)
{
cout << "超出范围,插入错误" << endl;
return 0;
}
else if((GetNums(head) + 1) == n)
{
Linklist q = head->next;
while (q->next != nullptr)
{
q = q->next;
}
//cout << q->date;
Linklist p = new DoubleNode;
p->date = value;
q->next = p;
p->next = nullptr;
p->prev = q;
}
else
{
//找到第n个节点的前一节点
Linklist p = head->next;
for(int i = 1; i < n - 1; ++i)
{
p = p->next;
}
Linklist newNode = new DoubleNode;
//插入
newNode->date = value;
newNode->next = p->next;
newNode->prev = p;
p->next->prev = newNode;
p->next = newNode;
}
}
else
{
cout << "该链表为空" << endl;
return 0;
}
return head;
}
//双向链表的删除--在链表head的第n个位置删除该元素
Linklist DeleteElm(Linklist head, int n)
{
//判断合法输入
if (!GetNums(head))
{
cout << "该链表为空。" << endl;
return 0;
}
else if (n < 0 || n > GetNums(head))
{
cout << "超出链表范围" << endl;
return 0;
}
//找到第n个节点的指针
else
{
Linklist p = head->next;
for(int i = 1;i < n; ++i)
{
p = p->next; //此时p指向第n个节点
}
p->prev->next = p->next;
p->next->prev = p->prev;
p->next = p->prev = p;
delete p;
}
return head;
}
//双向链表的销毁
void DestoryList(Linklist &head)
{
Linklist p = nullptr;
while (head->next != nullptr)
{
p = head;
head = head->next;
delete p;
}
delete head;
head = nullptr;
}
//双向链表的遍历--正向遍历
void ReadList(Linklist head)
{
if (head ==nullptr)
{
cout << "该链表为空" << endl;
}
Linklist p = head->next; //p指向链表中的第一个节点
cout << "链表的读取:";
while (p !=nullptr)
{
cout << p->date << " ";
p = p->next;
}
}
//双向链表的反向遍历
void ListReverse(Linklist head)
{
if (head ==nullptr)
{
cout << "链表为空" << endl;
}
Linklist p = head->next;
while (p->next != nullptr)
{
p = p->next;
}
//p 为尾节点的指针
cout << "反向链表读取:";
while (p->prev != nullptr) //p->next != nullptr 不读取最后一个元素
{ //p != nullptr 读取最后一个元素
cout << p->date << " ";
p = p->prev;
}
}
int main()
{
Linklist head;
CreateList(head, 10);
ReadList(head);
cout << endl;
ListReverse(head);
cout << endl;
InsertList(head, 11, 100);
cout << "插入后的链表为:" << endl;
ReadList(head);
cout << endl;
cout << "删除后的链表为:" << endl;
DeleteElm(head, 5);
ReadList(head);
DestoryList(head);
cout << endl;
if (head != nullptr)
{
cout << "链表还有:" << head->date << endl;
}
else
{
cout << "该链表为空";
}
return 0;
}
输出为
链表的读取:18 16 14 12 10 8 6 4 2 0
反向链表读取:0 2 4 6 8 10 12 14 16 18
插入后的链表为:
链表的读取:18 16 14 12 10 8 6 4 2 0 100
删除后的链表为:
链表的读取:18 16 14 12 8 6 4 2 0 100
该链表为空