文章目录
概要:本期学习循环双链表的结构、基本操作的实现。
一、什么是循环双链表?
循环双链表是基于双链表的基础上,增加了尾结点的后继指针指向头结点,头结点的前驱指针指向尾结点的区别。
具体结构如下图所示:
二、循环双链表的操作实现
0.循环双链表的结构和初始化
class CyclicDoubleLinkedList
{
private:
class Node{
public:
QString data;
Node *next;
Node *pre;
};
Node *head;
int length;
public:
CyclicDoubleLinkedList();
};
CyclicDoubleLinkedList::CyclicDoubleLinkedList()
{
head = new Node;
head->next = head;//指向自身
head->pre = head;//指向自身
head->data = "";
length = 0;
}
1.创建循环双链表
头插法
void CyclicDoubleLinkedList::HeadCreateCyclicDoubleLinkedList(int n)
{
Node *_node = new Node;
_node = head;
length = n;
int i = 0;
while(i < n)
{
qDebug()<<QStringLiteral("请输入第")<<i<<QStringLiteral("个节点的值:")<<endl;
Node *_newNode = new Node;
string str;
cin>>str;
_newNode->data = QString::fromStdString(str);
if(_node->next == head)//空链表
{
_newNode->next = head;
_node->next = _newNode;
_newNode->pre = _node;
}
else
{
_newNode->next = _node->next;//1.将新节点的后继指针指向当前节点的后一节点
_node->next->pre = _newNode;//2.将当前节点的后一节点的前驱指针指向新节点
_newNode->pre = _node;//3.将新节点的前驱指针指向当前节点
_node->next = _newNode;//4.将当前节点的后继指针指向新节点
}
i++;
}
}
尾插法
void CyclicDoubleLinkedList::TailCreateCyclicDoubleLinkedList(int n)
{
Node *_node = new Node;
_node = head;
length = n;
int i = 0;
while(i < n)
{
qDebug()<<QStringLiteral("请输入第")<<i<<QStringLiteral("个节点的值:")<<endl;
Node *_newNode = new Node;
string str;
cin>>str;
_newNode->data = QString::fromStdString(str);
_newNode->next = head;//1.将新节点的后继指针指向头结点
head->pre = _newNode;//2.将头节点的前驱指针指向新节点(尾插法,当前节点永远为尾结点)
_newNode->pre = _node;//3.将新节点的前驱指针指向当前节点
_node->next = _newNode;//4.将当前节点的后继指针指向新节点
_node = _node->next;//当前指向节点后移
i++;
}
}
2.打印循环双链表
void CyclicDoubleLinkedList::DisplayCyclicDoubleLinkedList()
{
if(length == 0)
{
qDebug()<<QStringLiteral("链表为空!")<<endl;
return ;
}
Node *_node = head->next;//节点1
int i = 0;
while(_node)
{
qDebug()<<QStringLiteral("第")<<i++<<QStringLiteral("个节点的数据:")<<_node->data<<endl;
if(_node->next == head)
{
return ;
}
_node = _node->next;
}
}
3.在循环双链表中增加节点
void CyclicDoubleLinkedList::BackInsertNodeToCyclicDoubleLinkedList(int index, QString data)
{
if(index < 0 || index >=length)
{
qDebug()<<QStringLiteral("输入位置有误!")<<endl;
return ;
}
Node *_node = new Node;
if(length == 0)
{
_node = head;
}
else
{
_node = head->next;
}
int i = 0;
while(_node)
{
if(i == index -1)
{
Node *_newNode = new Node;
_newNode->data = data;//赋值
_newNode->next = _node->next;//1.将新节点的后继指针指向当前节点的后一节点
_node->next->pre = _newNode;//2.将当前节点的后一节点的前驱指针指向新节点
_newNode->pre = _node;//3.将新节点的前驱指针指向当前节点
_node->next = _newNode;//4.将当前节点的后继指针指向新节点
length ++;
qDebug()<<QStringLiteral("节点插入成功!")<<endl;
return;
}
if(_node->next == nullptr)
{
qDebug()<<QStringLiteral("节点插入失败!")<<endl;
return ;
}
_node = _node->next;
i++;
}
}
4.删除双链表中指定节点
void CyclicDoubleLinkedList::DeleteNodeFromCyclicDoubleLinkedList(int index)
{
if(index < 0 || index >=length)
{
qDebug()<<QStringLiteral("输入位置有误!")<<endl;
return ;
}
Node *_node = new Node;
if(length == 0)
{
qDebug()<<QStringLiteral("链表为空,无法进行删除操作!")<<endl;
return ;
}
else
{
_node = head->next;
}
int i = 0;
while(_node)
{
if(i == index-1)
{
Node *_delNode = _node->next;
_node->next = _delNode->next;
_delNode->next = _node;
delete _delNode;
_delNode = NULL;
qDebug()<<QStringLiteral("节点删除成功!")<<endl;
length --;
return ;
}
if(_node->next == nullptr)
{
qDebug()<<QStringLiteral("节点删除失败!")<<endl;
return ;
}
_node = _node->next;
i++;
}
}
结尾
本期对于循环双链表的学习就到这,下期我们学习栈的相关知识。