双向循环链表
C++容器的list的底层数据结构是双向循环链表
节点的定义
//定义双向链表的节点类型
struct Node
{
Node(int data=0)
: data_(data)
, next_(nullptr)
, pre_(nullptr)
{}
int data_;//数据域
Node* next_;//指向下一个节点
Node* pre_;//指向前一个节点
};
构造函数
public:
DoubleCircleLink()//构造函数
{
head_ = new Node();
head_->next_ = head_;
head_->pre_ = head_;
}
析构函数
我们总是删除第一个有效节点(p指向的节点),然后把删除的节点的前面节点和当前删除的节点的后面节点连接起来。
当我们删除完最后一个有效节点时,就剩下一个头节点,我们把头节点delete掉
~DoubleCircleLink()//析构函数
{
Node* p = head_->next_;//删除p指向的节点
while (p != head_)
{
head_->next_ = p->next_;
p->next_->pre_ = head_;
delete p;
p = head_->next_;//让p重新指向第一个节点,进行删除
}
delete head_;
head_ = nullptr;
}
如果只有1个有效节点,上面代码也适用!
head头的next和pre都指向了head自己!然后delete p;
如果只有一个头节点呢?
p指向的就是头节点,不进入while循环。
执行delete head_;
head_=nullptr;
头插法
我们现在要头插一个89节点
头插法不涉及头节点的pre域和尾节点的next域
//头插法 O(1)
void InsertHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
node->pre_ = head_;
head_->next_->pre_ = node;
head_->next_ = node;
}
如果原来的链表是空链表,只有一个头节点,现在头插一个新节点89
和原来的代码也适用
尾插法
我们现在要尾插1个节点99
我们要修改89这个末尾节点的next域和99的pre域,99的next域,head头节点的pre域
//尾插法 O(1)
void InsertTail(int val)
{
Node* p = head_->pre_;//尾节点
//p->尾节点
Node* node = new Node(val);
node->pre_ = p;
p->next_ = node;
node->next_ = head_;
head_->pre_ = node;
}
节点的删除
//节点删除
void Remove(int val)
{
Node* p = head_->next_;
while (p != head_)
{
if (p->data_ == val)
{
//删除p指向的节点
p->pre_->next_ = p->next_;
p->next_->pre_ = p->pre_;
delete p;
return;
}
else
{
p = p->next_;
}
}
}
节点搜索
//节点搜索
bool Find(int val)
{
Node* p = head_->next_;
while (p != head_)
{
if (p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
return false;
}
链表输出
//链表节点输出
void Show()
{
Node* p = head_->next_;
while (p != head_)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
测试代码
#include <iostream>
using namespace std;
//定义双向链表的节点类型
struct Node
{
Node(int data = 0)
: data_(data)
, next_(nullptr)
, pre_(nullptr)
{}
int data_;//数据域
Node* next_;//指向下一个节点
Node* pre_;//指向前一个节点
};
//双向循环链表
class DoubleCircleLink
{
public:
DoubleCircleLink()//构造函数
{
head_ = new Node();
head_->next_ = head_;
head_->pre_ = head_;
}
~DoubleCircleLink()//析构函数
{
Node* p = head_->next_;
while (p != head_)
{
head_->next_ = p->next_;
p->next_->pre_ = head_;
delete p;
p = head_->next_;//让p重新指向第一个节点,进行删除
}
delete head_;
head_ = nullptr;
}
public:
//头插法 O(1)
void InsertHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
node->pre_ = head_;
head_->next_->pre_ = node;
head_->next_ = node;
}
//尾插法 O(1)
void InsertTail(int val)
{
Node* p = head_->pre_;//尾节点
//p->尾节点
Node* node = new Node(val);
node->pre_ = p;
p->next_ = node;
node->next_ = head_;
head_->pre_ = node;
}
//节点删除
void Remove(int val)
{
Node* p = head_->next_;
while (p != head_)
{
if (p->data_ == val)
{
//删除p指向的节点
p->pre_->next_ = p->next_;
p->next_->pre_ = p->pre_;
delete p;
return;
}
else
{
p = p->next_;
}
}
}
//节点搜索
bool Find(int val)
{
Node* p = head_->next_;
while (p != head_)
{
if (p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
return false;
}
//链表节点输出
void Show()
{
Node* p = head_->next_;
while (p != head_)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
private:
Node* head_;//指向头节点
};
int main()
{
DoubleCircleLink dlink;
dlink.InsertHead(100);
dlink.InsertTail(20);
dlink.InsertTail(12);
dlink.InsertTail(78);
dlink.InsertTail(32);
dlink.InsertTail(7);
dlink.InsertTail(90);
dlink.Show();
dlink.InsertHead(200);
dlink.Show();
dlink.Remove(200);
dlink.Show();
dlink.Remove(90);
dlink.Show();
dlink.Remove(78);
dlink.Show();
}