北邮22信通:复习补充:双向链表的实现

北邮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;
}

代码效果图:

运行结果:

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青山入墨雨如画

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值