二叉树的实现(递归实现)

前言:本文讲解通过递归的方式实现二叉树的一些基本接口。

目录

通过左右子树的方式实现二叉树:

二叉树的遍历:

 求二叉树结点的个数:

二叉树所有节点的个数:

二叉树叶子节点的个数: 

求第k层节点的节点的个数 :

找二叉树中值为x的节点

求二叉树的高度:

构建二叉树:

销毁二叉树:

重头戏:中序遍历

判断二叉树是否是完全二叉树 


通过左右子树的方式实现二叉树:

结构体的定义:

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType val;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

二叉树的遍历:

前序:根 ,左子树, 右子树

中序:左子树 ,根 ,右子树

后序: 左子树, 右子树, 根

根据上图分别走一遍前中后序:

前序:A ,B,NULL,NULL,C,NULL,NULL

中序:NULL,B,NULL,A,NULL,C,NULL

后序:NULL,NULL,B,NULL,NULL,C,A 

想要理解前中后序需要了解递归

每一棵树都可以看成 根   左子树   右子树三部分组成。

代码实现:

//前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("null ");
		return;
	}

	printf("%c ", root->val);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

深入理解代码:

以下是上面代码的函数递归调用的代码走读情况。

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("null ");
		return;
	}


	BinaryTreeInOrder(root->left);
	printf("%d ", root->val);
	BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("null ");
		return;
	}


	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ", root->val);
}

 求二叉树结点的个数:

二叉树所有节点的个数:

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

将问题分解:

如果 root为NULL,返回0;

每个二叉树结点的个数等于左子树节点的个数+右子树节点的个数+根(1)

代码深入理解:

二叉树叶子节点的个数: 

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;

	return BinaryTreeLeafSize(root->left)+BinaryTreeLeafSize(root->right);
}

 将问题分解:

如果root为NULL,返回0;

如果左右子树为NULL,该节点为叶子节点就返回1;

二叉树的叶子节点的个数等于左子树叶子节点的个数+右子树叶子节点的个数。

求第k层节点的节点的个数 :

代码:

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root,int k)
{
	if (root == NULL)
		return 0;
	if (k==1)//此时root不等于空
		return 1;

	return BinaryTreeLevelKSize(root->left,k-1) + BinaryTreeLevelKSize(root->right,k-1);
}

分解问题:

将问题可以看成: 第K层节点的个数 = 左子树第K-1层节点的个数+右子树K-1层节点的个数

如果root为NULL,返回0;

如果层数为1且该root不为NULL时,返回1


找二叉树中值为x的节点

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->val == x)
	{
		return root;
	}
	BTNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1)
		return ret1;
	BTNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2)
		return ret2;
	return NULL;
}

注意:要创建一个变量接受返回值,然后再返回,如果直接用函数返回返回值,那么就会出现多次重复调用.

分解问题:

找整棵树的问题转化为,找左子树和找右子树的问题

如果root为NULL,返回NULL

如果找到root->val==x,直接返回该节点的地址,

如果左右子树都没有x这个值ULL.

求二叉树的高度:

代码:

//求二叉树的高度
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;

	int leftheight = BinaryTreeHeight(root->left);
	int rightheight = BinaryTreeHeight(root->right);

	return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}

 问题分解:

二叉树的高度 = 左右子树中高度最高的高度+1(根)

构建二叉树:

// 通过前序遍历的数组"ABC###D##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType*arr,int* pi)
{
	if (arr[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail");
		return NULL;
	}
	root->left = NULL;
	root->right = NULL;
	root->val = arr[(*pi)++];
	root->left = BinaryTreeCreate(arr, pi);
	root->right = BinaryTreeCreate(arr, pi);
	return root;
}

‘#’是NULL

疑问:数组下标的指针pi,如果传值的话,就是临时拷贝

如果传的是指针的话,因为是递归,调用递归的被调用的函数中i的改变不会改变调用该函数中的i的值,因为是值拷贝,如果还不理解的话,可以看一下关于函数值调用和址调用的区别。

销毁二叉树:

// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

二叉树的销毁采用后续遍历,如果采用前序或后序会非法访问,并且释放不干净。


重头戏:中序遍历

什么是中序遍历?

就是一层一层的遍历。

上图中序遍历的结果是: 1,2,3,4

那么如何实现中序遍历呢?

可以通过队列来实现,现将根节点入队列

每个元素出队列时,打印该节点的值,并将该元素的左右子树的根节点入队列,如果节点为NULL,那么就不入队列,直至队列为空为止

这有一副流程图:

 代码:

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);//初始化队列
	if(root)
		QueuePush(&q,root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);//获得队头数据
		QueuePop(&q);
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
		printf("%c ", front->val);
	}
}

注意:这里队列中的存储的元素的数据类型为,二叉树节点的指针

完成这个代码需要用到以前写过的队列的代码

如果有需要这里有链接,数据结构: 实现初阶数据结构的代码 (gitee.com),如果不会队列的话,也可以看我以前的博客写的队列。

typedef BTNode* QDataType;
typedef struct QNode
{
	struct QNode* next;
	QDataType val;
}QNode;

判断二叉树是否是完全二叉树 

这个思路跟上面中序遍历的思路一样,都需要用到队列,不同的是,中序遍历不将NULL入队列,

而这个如果左右子树的根为NULL,仍入队列。 

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL)
		{
			break;
		}
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
			return false;
	}
	return true;
}

思路: 第一次出队列的元素为NULL时,就一直将队列中的元素一直出队列,如果全为NULL则为完全二叉树只要有一个不为NULL,那么就不是完全二叉树。

 

结语:这就是今天的分享,希望看到这篇博客的人都能有所收获。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

传输层安全性 (TLS)

传输层安全 (TLS) 旨在提供传输层的安全性。TLS 源自称为安全套接字层 (SSL)的安全协议。 TLS 确保任何第三方都无法窃听或篡改任何消息。 TLS 有几个好处: ● 加密: TLS/SSL 可以帮助使用加密来保护传输的数据。 ● 互操作性: TLS/S…

PHP框架 Laravel

现在因为公司需求,需要新开一个Laravel框架的项目,毫无疑问,我又被借调过去了,最近老是被借调,有点阴郁,不过反观来看,这也是好事,又可以复习和巩固一下自己的知识点,接下…

第八大奇迹

目录 题目描述 输入描述 输出描述 输入输出样例 示例 输入 输出 运行限制 原题链接 代码思路 题目描述 在一条 R 河流域,繁衍着一个古老的名族 Z。他们世代沿河而居,也在河边发展出了璀璨的文明。 Z 族在 R 河沿岸修建了很多建筑&#xff0c…

[Algorithm][动态规划][简单多状态DP问题][买卖股票的最佳时机 III][买卖股票的最佳时机 Ⅳ]详细讲解

目录 1.买卖股票的最佳时机 III1.题目链接2.算法原理详解3.代码实现 2.买卖股票的最佳时机 IV1.题目链接2.算法原理详解3.代码实现 1.买卖股票的最佳时机 III 1.题目链接 买卖股票的最佳时机 III 2.算法原理详解 注意:本题为了便于初始化,有较多细节服…

Java之Writer类:探索Java中的输出流

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…

在CentOS 8上卸载与安装MySQL 8的详细步骤

关键词:MySQL 8安装、CentOS 8、YUM源配置、卸载MySQL、MySQL残留文件删除、首次登录MySQL临时密码、服务状态检查、MySQL社区服务器 阅读建议:本文适合需要在CentOS 8操作系统上部署最新MySQL 8数据库的系统管理员或开发者阅读。文中步骤简洁清晰&#…

Spring+SpringBoot面试总结(近两万字)

SpringSpringBoot面试总结 一、Spring Bean1.1、bean的生命周期(对象的创建使用销毁)1.1.1、准备工作1.1.2、创建Bean对象1.1.3、注册销毁 1.2、 bean的作用域1.2.1、配置方式 1.3、 spring 自动装配 bean 有哪些方式(存疑存疑)1.…

452. 用最少数量的箭引爆气球(中等)

452. 用最少数量的箭引爆气球 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转:452. 用最少数量的箭引爆气球 2.详细题解 引爆所有气球,弓箭数要最少,那么每支弓箭尽量多的引爆气球,采用贪心策略。对于…

基于小波熵阈值的心电信号R波检测算法(MATLAB)

心脏兴奋电活动过程可由心电信号(ECG)来反映,心电信号也是医学上对心血管疾病诊断的重要科学依据。心电信号具有一定的随机性且一般情况下十分微弱,在信号采集、放大及变换过程中,心电信号容易受到人体呼吸及检测仪器等因素影响,从…

在ARM开发板上,栈大小设置为2MB(常用设置)里面存放的数据

系列文章目录 在ARM开发板上,栈大小设置为2MB(常用设置)里面存放的数据 在ARM开发板上,栈大小设置为2MB(常用设置)里面存放的数据 系列文章目录 在ARM开发板上,栈(Stack)…

linux下cp和mv命令显示进度条

1.查看当前系统下coreutils工具包的版本号: [rootk8s-master ~]# rpm -qa | grep -w coreutils coreutils-8.22-24.el7_9.2.x86_64当前版本为8.22。 因为cp 和 mv 命令由 coreutils 软件包提供,所以需要重新下载 coreutils 软件包配置补丁 2.下载core…

148.栈与队列:前K个高频元素(力扣)

代码解决 class Solution { public:// 自定义比较类,用于优先队列(小顶堆)class mycomparison{public:// 重载操作符,用于比较两个pair,基于pair的第二个值(频率)bool operator()(const pair&l…

网页图片加载慢的求解指南

网页/图片加载慢的求解指南 一、前言与问题描述 今天刚换上华为的HUAWEI AX3 Pro New,连上WIFI后测速虽然比平时慢,但是也不算太离谱,如下图所示: 估计读者们有也和作者一样,还没意识到事情的严重性😁。 …

UE_地编教程_创建地形洞材质

个人学习笔记,不喜勿喷。侵权立删! 使用地形洞材质来遮罩地形上特定位置的可视性和碰撞。如要在山脉侧面创建进入洞穴的入口,此操作将非常有用。可使用地形材质和地形洞材质的相同材质,但注意:对比不使用不透明蒙版的…

基于Cloudflare/CloudDNS/GitHub使用免费域名部署NewBing的AI服务

部署前准备: Cloudflare 账号 https://dash.cloudflare.com/login CloudDNS 账号 https://www.cloudns.net/ GitHub 账号 https://github.com/Harry-zklcdc/go-proxy-bingai Cloudflare 部署 Worker CloudDNS 获取免费二级域名 GitHub New Bing Ai 项目 https://git…

Linux系统硬盘分区

文章目录 一、硬盘和分区1.1 硬盘的概念1.2 硬盘分区的类别1.3 硬盘分区的方式1.3.1 MBR分区1.3.2 GPT分区 1.4 硬盘分区的意义1.4.1 分区的作用1.4.2 分区的缺点 二、如何建立分区2.1 分区命令2.1.1 fdisk命令2.1.2 gdisk命令 2.2 建立分区2.2.1 建立MBR分区建立主分区建立扩展…

电脑如何在网页上下载视频 浏览器如何下载网页视频

对于现代职场人士而言,在日常生活中难免需要下载各种短视频,IDM下载加速器可以轻松获取抖音、快手等平台的无水印短视频文件。 Internet Download Manager,简称IDM。功能强大的网络下载器。您不需要多余的操作,IDM 能捕获您的下载…

实战

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 实战一:模拟支付宝蚂蚁森林的能量产生过程 支付宝的蚂蚁森林通过日常的走步、生活缴费、线下支付、网络购票、共享单车等低碳、环保行为…

行为设计模式之策略模式

文章目录 概述原理结构图 代码实现小结 概述 策略模式(strategy pattern)的原始定义是:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。 在软件开发中也会遇到相似的情况&…

【Lexus.4】Executive Sedan——Dismantling Follow-up

文章目录 【碰撞测试】前后防撞钢梁偏置碰撞A/B/C柱,边梁抗拉、屈服强度 【底盘】平整度护板(发动机,底盘)前副车架结构前悬架形式后悬架形式与材质簧下质量 【发动机】【轮上马力】【零部件供应商】 来自2021《懂车大爆炸》——是…