双向链表
节点可以向后遍历,也可以向前遍历
节点的定义
//定义双向链表的节点类型
struct Node
{
Node(int data=0)
: data_(data)
, next_(nullptr)
, pre_(nullptr)
{}
int data_;//数据域
Node* next_;//指向下一个节点
Node* pre_;//指向前一个节点
};
//双向链表
class DoubleLink
{
private:
Node* head_;//指向头节点
构造函数和析构函数
public:
DoubleLink()//构造函数
{
head_ = new Node();
}
~DoubleLink()//析构函数
{
Node* p = head_;
while (p != nullptr)
{
head_ = head_->next_;
delete p;
p = head_;
}
}
头插法
假如现在只有1个头节点,是空链表
现在要生成一个新的节点
我们要改33节点的pre指针域和head头节点的next指针域
假如现在我们还要再头插1个节点
33的pre指针域和25的next指针域和25的pre指针域和head头节点的next指针域都要修改!!!
我们得先修改新生成节点node的前后指针域
33节点地址在head头节点的next域存储着呢。
我们修改25节点的next域
我们修改25节点的pre域
然后我们修改33节点的pre域
最后我们处理head头节点的next域
//头插法
void InsertHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
node->pre_ = head_;
if (head_->next_ != nullptr)
{
head_->next_->pre_ = node;
}
head_->next_ = node;
}
现在的代码是对上面所叙述的两种情况都适用!
尾插法
我们尾插一个节点66,只需要修改尾结点的next域和新生成的节点66的pre域
//尾插法
void InsertTail(int val)
{
Node* p = head_;
while (p->next_ != nullptr)
{
p = p->next_;
}
//p->尾节点
Node* node = new Node(val);
node->pre_ = p;
p->next_ = node;
}
链表节点输出
//链表节点输出
void Show()
{
Node* p = head_->next_;
while (p != nullptr)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
节点删除
假设我们现在要删除节点33
我们定义1个指针找到33这个节点
这次就不用定义2个指针了。因为33节点可以向后和向前遍历。
我们把33节点删除了,要把25节点和66节点要连起来,25的next域记录66节点的地址,然后66的pre域记录25节点的地址。
//节点删除
void Remove(int val)
{
Node* p = head_->next_;
while (p != nullptr)
{
if (p->data_ == val)
{
//删除p指向的节点
p->pre_->next_ = p->next_;
if (p->next_ != nullptr)
{
p->next_->pre_ = p->pre_;
}
//Node* next = p->next_;//删除所有值为val的节点
delete p;
//p = next;//删除所有值为val的节点
return;
}
else
{
p = p->next_;
}
}
}
节点搜索
//节点搜索
bool Find(int val)
{
Node* p = head_->next_;
while (p != nullptr)
{
if (p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
return false;
}
测试代码
#include <iostream>
using namespace std;
//定义双向链表的节点类型
struct Node
{
Node(int data=0)
: data_(data)
, next_(nullptr)
, pre_(nullptr)
{}
int data_;//数据域
Node* next_;//指向下一个节点
Node* pre_;//指向前一个节点
};
//双向链表
class DoubleLink
{
public:
DoubleLink()//构造函数
{
head_ = new Node();
}
~DoubleLink()//析构函数
{
Node* p = head_;
while (p != nullptr)
{
head_ = head_->next_;
delete p;
p = head_;
}
}
public:
//头插法
void InsertHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
node->pre_ = head_;
if (head_->next_ != nullptr)
{
head_->next_->pre_ = node;
}
head_->next_ = node;
}
//尾插法
void InsertTail(int val)
{
Node* p = head_;
while (p->next_ != nullptr)
{
p = p->next_;
}
//p->尾节点
Node* node = new Node(val);
node->pre_ = p;
p->next_ = node;
}
//节点删除
void Remove(int val)
{
Node* p = head_->next_;
while (p != nullptr)
{
if (p->data_ == val)
{
//删除p指向的节点
p->pre_->next_ = p->next_;
if (p->next_ != nullptr)
{
p->next_->pre_ = p->pre_;
}
//Node* next = p->next_;
delete p;
//p = next;
return;
}
else
{
p = p->next_;
}
}
}
//节点搜索
bool Find(int val)
{
Node* p = head_->next_;
while (p != nullptr)
{
if (p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
return false;
}
//链表节点输出
void Show()
{
Node* p = head_->next_;
while (p != nullptr)
{
cout << p->data_ << " ";
p = p->next_;
}
cout << endl;
}
private:
Node* head_;//指向头节点
};
int main()
{
DoubleLink 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();
}