北邮22信通:(12)二叉树的遍历书上代码完整版

news2024/12/30 0:56:28

北邮22信通一枚~   

跟随课程进度每周更新数据结构与算法的代码和文章 

持续关注作者  解锁更多邮苑信通专属代码~

上一篇文章:

下一篇文章:

目录

一.储存最简单数据类型的二叉树

代码部分:

代码效果:

运行结果:

二.存储相对较复杂的数据类型的二叉树

代码部分:

代码效果图:

运行结果: 


***说明***

1.书上描绘的是采用二叉链表作为存储结构的二叉树。本代码完全遵从书上代码。小编最近会尝试用三叉链表写写(

2.遍历二叉链表的关键思想:递归。函数的递归调用

3.书上只是给出了各种遍历方法在模板类中的书写方法,并有一定错误。本代码将其余部分完善(包括主函数和存储数据的数据类型)并将错误修改完毕,读者可以放心使用。本篇文章基于书上遍历算法,提供了两个例子。这两个例子的主要区别是,二叉树存储数据的数据类型不同。第一个例子是存储了简单的数据类型,比如int;第二个例子存储了相对较复杂的数据类型,为一个类。希望对读者有所帮助。

3.关于编写代码时新学到的知识:#define  MAXSIZE 1e5这种写法是不被VS2022接受的。必须写成#define MAXSIZE 100000或者const int MAXSIZE=1e5;

4.有读者可能会这样问:在模板类中将root定义在public区域,这样能够保证数据的安全性吗?这样做的好处是什么?

首先回答第一个问题,数据相对安全。将根节点写在public中,外界只能访问到这一个结点中的数据,这对于想要得到数据的一方显然是毫无用处的;如果不通过成员函数的调用,外界就不能获取其他结点的信息。所以将root定义在public区域,能够保证数据的安全性。

第二个问题。这样做的好处,其实就是为了书写其他函数和主函数的时候调用根结点时能够方便一些。如果将root设置成为private中的数据也未尝不可,那就需要在public区域中书写一个getroot函数,具体实现函数如下:

    binnode<temp>* getroot() { return this->root; }

后面每次用到root根节点的时候,都要调用一次这个函数(好麻烦)

5.想到啥再补充 有问题评论区找我

***说明结束***

一.储存最简单数据类型的二叉树

        就是在主函数中,我们将temp的位置填入最简单的数据类型,实现最简单的二叉树遍历。这个二叉树每个结点中的数据域将都是这个最简单的数据类型,二叉树的结构看起来也相对简单。

        本代码传入的数据类型是int。也就是我们建立了一个存储整型数据的二叉树。

下面我们来看代码:

代码部分:

#include<iostream>
#define MAXSIZE 100000
//注意:不能将上面这行宏定义写成
//#define MAXSIZE 1e5
//上面这样写会报错!!
using namespace std;

template<class temp>
struct binnode
{
	temp data;
	binnode<temp>* leftchild;
	binnode<temp>* rightchild;
};

template<class temp>
class bintree
{
private:
	void create(binnode<temp>*& r, temp data[], int i, int n);
	void release(binnode<temp>* r);
public:
	binnode<temp>* root;
	bintree(temp data[], int n);
	void preorder(binnode<temp>* r);
	void inorder(binnode<temp>* r);
	void postorder(binnode<temp>* r);
	void levelorder(binnode<temp>* r);

	~bintree();
};

template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{

	if (i <= n && data[i - 1] != 0)
	{
		r = new binnode<temp>;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);
		/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template<class temp>
bintree<temp>::bintree(temp data[], int n)
/*书上代码错误2:构造函数不能有返回值类型,但是书上多加了一个void*/
/*如果构造函数的声明语句写成
void bintree<temp>::bintree(temp data[], int n),
程序会报错:不能在构造函数上指定返回值类型*/
{
	create(this->root, data, 1, n);
}

template<class temp>
void bintree<temp>::preorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		cout << r->data;//访问结点;
		preorder(r->leftchild);//遍历左子树
		preorder(r->rightchild);//遍历右子树
	}
}

template<class temp>
void bintree<temp>::inorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::postorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template<class temp>
void bintree<temp>::levelorder(binnode<temp>* R)
{
	binnode<temp>* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode<temp>* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template <class temp>
void bintree<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

/*书上代码错误3:不能在析构函数上指定返回值类型,但是书上代码多了一个void*/
template<class temp>
bintree<temp>::~bintree()
{
	release(this->root);
}

int main()
{
	int a[5] = { 1,2,3,4,5 };
	bintree<int>bintreee(a, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);
	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	return 0;
}

代码效果:

运行结果:

二.存储相对较复杂的数据类型的二叉树

        定义了一个相对复杂的数据类型:一个类。需要注意的是,如果使用类作为存储的数据类型,有一个地方需要稍微改动一下:见原代码第59~63行。

代码部分:

#include<iostream>
#define MAXSIZE 100000
//注意:不能将上面这行宏定义写成
//#define MAXSIZE 1e5
//上面这样写会报错!!
using namespace std;
class student
{
private:
	int ID;
	string name;
public:
	int existence;
	student()
	{
		this->ID = 0;
		this->name = "unknown name";
		this->existence = 0;
	}
	student(int ID, string name)
	{
		this->ID = ID;
		this->name = name;
		this->existence = 1;
	}
	friend ostream& operator<<(ostream& output, student& s)
	{
		output << s.ID << " " << s.name << endl;
		return output;
	}
};

template<class temp>
struct binnode
{
	temp data;
	binnode<temp>* leftchild;
	binnode<temp>* rightchild;
};

template<class temp>
class bintree
{
private:
	void create(binnode<temp>*& r, temp data[], int i, int n);
	void release(binnode<temp>* r);
public:
	binnode<temp>* root;
	bintree(temp data[], int n);
	void preorder(binnode<temp>* r);
	void inorder(binnode<temp>* r);
	void postorder(binnode<temp>* r);
	void levelorder(binnode<temp>* r);
	~bintree();
};

template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{
	/*书上代码的一个问题:data[i-1]!=0会报错,这是因为data的数据类型是temp,没法实现!=的运算*/
	//书上原代码
	//if (i <= n && data[i - 1] != 0)
	if (i <= n && data[i - 1].existence != 0)
	{
		r = new binnode<temp>;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template<class temp>
bintree<temp>::bintree(temp data[], int n)
/*书上代码错误2:构造函数不能有返回值类型,但是书上多加了一个void*/
/*如果构造函数的声明语句写成
void bintree<temp>::bintree(temp data[], int n),
程序会报错:不能在构造函数上指定返回值类型*/
{
	create(this->root, data, 1, n);
}

template<class temp>
void bintree<temp>::preorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		cout << r->data;//访问结点;
		preorder(r->leftchild);//遍历左子树
		preorder(r->rightchild);//遍历右子树
	}
}

template<class temp>
void bintree<temp>::inorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::postorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template<class temp>
void bintree<temp>::levelorder(binnode<temp>* R)
{
	binnode<temp>* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode<temp>* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template <class temp>
void bintree<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

/*书上代码错误3:不能在析构函数上指定返回值类型,但是书上代码多了一个void*/
template<class temp>
bintree<temp>::~bintree()
{
	release(this->root);
}

int main()
{
	system("color 0A");
	student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
	bintree<student>bintreee(stu, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	/*说明:这里体现了将根节点定义为public类型的好处,
	不然需要通过一个成员函数来实现这个功能,
	从数据保密性来看,这样做也是可以的:
	外部如果不通过调用成员函数,就只能访问根节点一个节点内的数据,
	但是其他任意节点内的数据都无法访问,安全性也相对较高。
	*/
	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);
	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	cout << endl;
	return 0;
}

代码效果图:

运行结果: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417867.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决JD-GUI-1.6.6 中文乱码

一、背景 在window环境下使用中遇到了乱码问题。 问题有两个&#xff1a; 一、从反编译代码的界面 CTRLC 复制是如果选中内容包含中文&#xff0c;贴到其他编辑器时&#xff0c;中文丢失。 二、打开xml文件、properties文件等包含中文时。中文在反编译界面中显示乱码。用其他工…

java反射教程

反射&#xff08;Reflection&#xff09;是 Java中的一种机制&#xff0c;它是一种特殊的面向对象编程技术。在 Java中&#xff0c;反射可以分为静态反射和动态反射两种。静态反射是指在 Java程序运行时才进行的一种反射&#xff0c;它可以保证程序运行时不会出现内存泄漏等错误…

数据分析的作用和意义?

数据分析的作用和意义&#xff1f;在当下数字化转型发展的大环境中&#xff0c;数据也成为企业商业成功与否的重要基础&#xff0c;如何利用好数据分析问题预测未来也成为更多企业面临的首要问题。而随时大数据的不断渗透&#xff0c;数据量和数据类型也越来越多&#xff0c;数…

asp.net车辆管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net车辆管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net车辆管理系统VS开发sqlserver数…

【CSIG图像图形技术挑战赛-开放世界目标检测竞赛】火热报名中!

竞赛名称&#xff1a;开放世界目标检测竞赛/Few Shot&#xff09;主办方: 中国图象图形学学会&#xff08;CSIG&#xff09;合作方: 360集团竞赛目的与意义&#xff1a;目标检测是计算机视觉中的核心任务之一&#xff0c;主要目的是让计算机可以自动识别图片中目标的类别&#…

Windows File Recovery使用教程

Windows File Recovery简介 Windows File Recovery是微软在2020年发布的命令提示符文件恢复工具&#xff0c;它不仅具有高成功率和高安全性&#xff0c;还适用于不同的文件系统和文件丢失场景。如果你需要从本地硬盘、USB设备、SD卡等设备中恢复意外丢失或删除的JPEG、PDF、…

分析Spring事务管理原理及应用

目录 一、Spring事务管理介绍 &#xff08;一&#xff09;基本理论 &#xff08;二&#xff09;实际工作中的举例 &#xff08;三&#xff09;简单应用举例 二、Spring事务配置介绍 &#xff08;一&#xff09;Spring事务属性介绍 传播属性&#xff08;传播行为&#xff…

车身控制模块BCM(Body Control Module)

1.BCM概述 车身控制模块BCM是高集成度的芯片。BCM的英文全称是Body Control Module。其控制对象是采用高灵敏度带唤醒及睡眠检测的高频收发器&#xff0c;实现车门车窗遥控上锁与开锁、电动后视镜、中控门锁、玻璃升降装置、车灯(远光灯、近光灯、位置灯、制动灯、转向灯、雾灯…

【RocketMQ】主从模式下的消费进度管理

在【RocketMQ】消息的拉取一文中可知&#xff0c;消费者在启动的时候&#xff0c;会创建消息拉取API对象PullAPIWrapper&#xff0c;调用pullKernelImpl方法向Broker发送拉取消息的请求&#xff0c;那么在主从模式下消费者是如何选择向哪个Broker发送拉取请求的&#xff1f; 进…

【Linux】项目自动化构建工具-make/Makefile

文章目录1.make/Makefile的重要性2.规则及使用使用规则3.Makefile编译多文件1.make/Makefile的重要性 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xf…

2023美赛春季赛Z题模型代码

已经完成模型代码&#xff0c;仅供大家参考&#xff0c;需要更多请看文末 一、问题分析 首先需要收集与奥运会举办城市/国家相关的历史数据。这需要涉及诸如经济、土地利用、人类满意度&#xff08;包括运动员和观众&#xff09;、旅行、基础设施建设、环境影响等多个方面。数…

(二)【软件设计师】计算机系统—CPU运算器控制器

文章目录一、CPU1.计算机硬件基本组成&#xff08;了解&#xff09;2.中央处理单元&#xff08;了解&#xff09;3.CPU组成4.例题二、运算器1.运算器有两个主要功能2.简要介绍运算器中各组成部件的功能三、控制器1.例题2.组成部分四、总结一、CPU 1.计算机硬件基本组成&#x…

让chatGPT当我的老师如何? 通过和chatGPT交互式学习,了解在ES中,一条JSON数据是如何写到磁盘上的

最近一直有一个问题&#xff0c;如鲠在喉。争取早一天解决&#xff0c;早一天踏踏实实的睡觉。 问题是&#xff1a;在ES中&#xff0c;一条JSON数据是如何写入到磁盘上的&#xff1f; 如何解决这个问题&#xff1f;我想到了chatGPT&#xff0c;还有lucene的学习资料。这篇文章&…

港科夜闻|香港科大(广州)创邻图数据联合实验室正式成立

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、香港科大(广州)创邻图数据联合实验室正式成立。未来&#xff0c;香港科大(广州)与「创邻科技」双方将围绕万亿级大图神经网络计算框架、海量数据的时序图处理、分布式原生图数据库事务及性能优化等前沿图技术领域研究展开深…

Cocos Creator的Hello World

0、文档 Cocos官网文档 1、下载 访问cocos官网下载Cocos Dashboard 安装时选项安装 Visual Studio 2017可以不勾选 注意&#xff1a;Cocos Dashboard的快捷方式文件名为CocosDashboard.exe&#xff0c;不要误认为是安装文件 2、注册、登录 注册/登录cocos网址 3、Cocos D…

深度学习之CD数据集创建

深度学习之数据集创建1. 原始文件相关文件路径2. 数据集创建2.1 数据格式一2.2 数据格式二1. 原始文件相关文件路径 原始路径 对于label图片文件&#xff0c;通道需要为单通道&#xff0c;如果不是单通道&#xff0c;训练数据会报错 报错信息例如&#xff1a;ValueError: Mask…

自然语言处理(八):Lexical Semantics

目录 1. Sentiment Analysis 2. Lexical Database 2.1 What is Lexical Database 2.2 Definitions 2.3 Meaning Through Dictionary 2.4 WordNet 2.5 Synsets 2.6 Hypernymy Chain 3. Word Similarity 3.1 Word Similarity with Paths 3.2 超越路径长度 3.3 Abstra…

波形失真总结

失真是输入信号与输出信号在幅度比例关系、相位关系及波形形状产生变化的现象。音频功放的失真分为电失真和声失真两大类。电失真是由电路引起的&#xff0c;声失真是由还音器件扬声器引起的。电失真的类型有&#xff1a;谐波失真、互调失真、瞬态失真。声失真主要是交流接口失…

idea使用之 单词拼写检查设置 分级管理

前言 idea的智能提示使用起来非常顺手, 拼接检查也是其中一项, 有些字段什么的, 不小心将单词的字母顺序写错了, idea的拼接检查就会提示(前提是字段命名规范,并且乱序之后的不再是一个具有意义的单词), 如此一来, 就能规避很多粗心大意的错误. 但是呢, 有些时候,项目中有些自…

用Claude和Stable Diffusion绘制《武松打虎》

绘制四大名著的经典画面 现在最火爆的AI&#xff0c;分为两类&#xff0c;一个是文本生成&#xff0c;一个是图片生成。如果让这两种结合到一起来&#xff0c;会是什么样的效果的。 这样是不是可能帮我们绘制很多场景下的图片&#xff0c;比如四大名著&#xff0c;帮我们的四…