北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
获取更多文章 请访问专栏:
北邮22信通_青山如墨雨如画的博客-CSDN博客
**说明**
最近复习看到书后有双向链表的题目,编出来供大家复习~
*********
目录
一.讲解
1.insert 增添函数
2.构造函数:
3.del删除函数:
4.change修改函数
5.search查找函数
二.代码部分及运行结果
完整代码
代码效果图:
运行结果:
一.讲解
小编实现的这个双向链表只涉及增删改查四个功能。下面先大体说一下思路。
结点结构包括数据域、左指针和右指针 ,左指针链接左边的相邻结点,右指针链接右边的相邻结点;
双向链表类的实现部分,成员属性包括整条链表的头指针和尾指针以及链表的长度;
为什么增添了尾指针,请读者带着问题先往下看;
成员函数包括类的构造函数和析构函数,增删改查4种功能的实现函数以及链表打印函数,下面逐个讲解这几个函数。
1.insert 增添函数
实现增添功能的过程如下图所示;
简单讲解一下插入过程的步骤:
首先申请一个temp大小的堆空间,用来存放新增结点;
初始化这个结点,数据域赋值为传入的参数,两个指针域均赋值为空指针;
找到插入的地方,比如传入的参数是3那就是找到第3个结点;
新增结点的右指针和第3个结点相连,
新增结点的左指针和第三个结点的前驱结点也就是第二个结点相连
(先将新增结点的两个指针连在链表上,
然后再断开原先链表的指针连接,并重新与新增链表相连);
断开前驱结点的右指针,将右指针和新增结点相连,
断开查找结点的左指针,将左指针与新增结点相连;执行完毕。
insert函数的代码:
template<class temp>
void linklist<temp>::insert(int i, temp x)
{
node<temp>* p = this->front->right;
while (--i)
p = p->right;
node<temp>* before_p = p->left;
node<temp>* s = new node<temp>;
s->data = x;
s->right = p;
s->left = before_p;
p->left = s;
before_p->right = s;
this->length++;
}
2.构造函数:
这里将讲解为什么要多引入一个尾指针成员属性。
其实构造函数无非就是数据的接连插入操作,所以我们完全可以调用insert函数来实现构造函数的头插法。但是面临的问题是,如上insert函数的实现过程,我们必须保证至少有两个结点,才能执行在这两个结点之间的插入操作。综上,新增尾指针。其实,不添加尾指针也可以实现构造函数,即如果链表中只存在头结点,则将新增结点直接接在头结点后面,以后再新增数据,就直接调用insert函数实现。但是增加了尾指针还有其他好处比如倒序遍历,使得某些方法变得更加简便。所以小编选择增加了一个链表尾指针的成员属性。
构造函数实现如下:
template<class temp>
linklist<temp>::linklist(temp a[], int n)
{
this->front = new node<temp>;
this->rear = new node<temp>;
this->front->left = NULL;
this->front->right = this->rear;
this->rear->left = this->front;
this->rear->right = NULL;
this->length = 0;
for (int i = n - 1; i >= 0; i--)
{
insert(1, a[i]);
this->length++;
}
}
3.del删除函数:
删除操作的大致思路如下:
找到要删除的结点,其前驱结点的右指针指向删除结点的后继结点,后继结点的左指针指向删除结点的前驱结点,最后删除要删除的结点,执行完毕。
实现过程如下:
template<class temp>
temp linklist<temp>::del(int i)
{
if (i > this->length)
throw"上溢!";
node<temp>* p = this->front->right;
while (--i)
p = p->right;
cout << "被删除的数据为:";
p->data.print();
p->left->right = p->right;
p->right->left = p->left;
temp tempdata = p->data;
return tempdata;
}
4.change修改函数
很简单,向单链表一样循环,找到要修改数据域的结点,修改数据域即可。
5.search查找函数
思路同上。
二.代码部分及运行结果
完整代码
#include<iostream>
using namespace std;
class student
{
private:
int ID;
string name;
public:
student()
{
this->ID = 0;
this->name = "nuknown_name";
}
student(int ID, string name)
{
this->ID = ID;
this->name = name;
}
void print()
{
cout << this->ID << " " << this->name << endl;
}
friend ostream& operator <<(ostream& output, student& s)
{
output << s.ID << " " << s.name << endl;
return output;
}
bool operator !=(student&s)
{
return (this->ID != s.ID) || (this->name != s.name) ? true : false;
}
};
template<class temp>
struct node
{
temp data;
node* left;
node* right;
};
template<class temp>
class linklist
{
private:
node<temp>* front;
node<temp>* rear;
int length;
public:
linklist()
{
this->front = new node<temp>;
this->rear = new node<temp>;
this->front->left = NULL;
this->front->right = this->rear;
this->rear->left = this->front;
this->rear->right = NULL;
this->length = 0;
}
linklist(temp a[], int n);
~linklist();
void insert(int i, temp x);
temp del(int i);
void change(int i, temp x);
void search(temp x);
void printlist();
};
template<class temp>
linklist<temp>::linklist(temp a[], int n)
{
this->front = new node<temp>;
this->rear = new node<temp>;
this->front->left = NULL;
this->front->right = this->rear;
this->rear->left = this->front;
this->rear->right = NULL;
this->length = 0;
for (int i = n - 1; i >= 0; i--)
{
insert(1, a[i]);
this->length++;
}
}
template<class temp>
linklist<temp>::~linklist()
{
node<temp>* p = this->front;
while (p != NULL)
{
this->front = p;
p = p->right;
delete front;
}
}
template<class temp>
void linklist<temp>::insert(int i, temp x)
{
node<temp>* p = this->front->right;
while (--i)
p = p->right;
node<temp>* before_p = p->left;
node<temp>* s = new node<temp>;
s->data = x;
s->right = p;
s->left = before_p;
p->left = s;
before_p->right = s;
this->length++;
}
template<class temp>
temp linklist<temp>::del(int i)
{
if (i > this->length)
throw"上溢!";
node<temp>* p = this->front->right;
while (--i)
p = p->right;
cout << "被删除的数据为:";
p->data.print();
p->left->right = p->right;
p->right->left = p->left;
temp tempdata = p->data;
return tempdata;
}
template<class temp>
void linklist<temp>::change(int i, temp x)
{
if (i > this->length)
throw "上溢!";
node<temp>* p = this->front->right;
while (--i)
p = p->right;
if (p->right == NULL)
{
cout << "未查询到数据!" << endl;
return;
}
p->data = x;
}
template<class temp>
void linklist<temp>::search(temp x)
{
node<temp>* p = this->front->right;
while ((p->right != NULL) && (p->data != x))
p = p->right;
if ((p->left == NULL)||(p->right==NULL))
{
cout << "未查询到数据!" << endl << endl;
return;
}
cout << "找到数据!" << endl;
p->data.print();
}
template<class temp>
void linklist<temp>::printlist()
{
node<temp>* p = this->front->right;
while (p->right != NULL)
{
p->data.print();
p = p->right;
}
cout << endl;
}
int main()
{
system("color 0A");
cout << "双链表数据如下:" << endl;
student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"liu"},{5,"zhao"} };
linklist<student>list(stu, 5);
list.printlist();
cout << "下面检验插入操作:" << endl;
cout << "插入学生的信息为:";
student stu1(6, "fu");
stu1.print();
list.insert(3, stu1);
cout << "双链表当前数据为:" << endl;
list.printlist();
cout << "下面检验删除操作:" << endl;
cout << "以删除成员3为例:" << endl;
cout << "执行函数……";
list.del(3);
cout << "双链表当前数据为:" << endl;
list.printlist();
cout << "下面检验查找操作:" << endl;
cout << "查找同学的信息为:";
stu1.print();
list.search(stu1);
cout << "下面检验替换操作:" << endl;
cout << "替换进来的同学信息为:";
student stu2(8, "zheng");
stu2.print();
list.change(2, stu2);
cout << "双链表当前数据为:" << endl;
list.printlist();
return 0;
}
代码效果图:
运行结果: