文章目录
概要:本期主要学习双链表的结构、头插法建表、尾插法建表以及双链表的操作实现。
一、双链表长啥样?
双链表是单链表的变形,增加了一个前驱指针,指向当前节点的前一节点。如下图所示:
二、双链表有什么特点?
双链表相对于单链表,最主要的区别是它多了一个前驱指针域,指向前一节点的地址。因此,双链表可以访问当前节点的前一节点,时间复杂度为O(1)。
三、双链表的操作实现
0.双链表的结构以及初始化
class DoubleLinkedList
{
private:
class Node
{
public:
Node() {
}
QString data;
Node *pre;//指向前一个节点,前驱指针
Node *next;//指向后一个节点,后继指针
};
Node *head;
int length;
public:
DoubleLinkedList();
};
DoubleLinkedList::DoubleLinkedList()
{
head = new Node;
head->data = "";
head->next = nullptr;
head->pre = nullptr;
length = 0;
}
1.头插法创建双链表
//头插法创建双链表(链表内节点顺序与输入顺序相反)
void DoubleLinkedList::HeadCreateDoubleLinkedList(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 == nullptr)//空链表
{
_newNode->next = nullptr;
_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++;
}
}
2.尾插法创建双链表
//尾插法创建双链表(链表内节点顺序与输入顺序一致)
void DoubleLinkedList::TailCreateDoubleLinkedList(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 = _node->next;//1.将新节点的后继指针指向当前节点的后一节点
// _node->next->pre = _newNode;//2.将当前节点的后一节点的前驱指针指向新节点(尾插法,当前节点永远为尾结点)
_newNode->pre = _node;//3.将新节点的前驱指针指向当前节点
_node->next = _newNode;//4.将当前节点的后继指针指向新节点
_node = _node->next;//当前指向节点后移
i++;
}
}
3.打印双链表
void DoubleLinkedList::DisplayDoubleLinkedList()
{
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 == nullptr)
{
return ;
}
_node = _node->next;
}
}
4.在双链表中插入节点
//在指定节点后插入节点
void DoubleLinkedList::BackInsertNodeToDoubleLinkedList(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++;
}
}
5.删除双链表中的节点
//删除指定节点
void DoubleLinkedList::DeleteNodeFromDoubleLinkedList(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++;
}
}
结尾
本期对于双链表的学习就到这,下期我们学习循环双链表:)