数据结构之二叉树详解[1]

news2024/11/17 19:49:06

在前面我们介绍了堆和二叉树的基本概念后,本篇文章将带领大家深入学习链式二叉树。

1.预备知识

2.二叉树结点的创建

3.二叉树的遍历 

3.1前序遍历

3.2中序遍历

3.3 后序遍历

4.统计二叉树的结点个数

5.二叉树叶子结点的个数

 6.二叉树第k层的结点个数

 7.总结


1.预备知识

由于二叉树的性质,我们在实现二叉树及其相关功能时会经常使用到递归的操作。

所以我们首先介绍一下递归算法。

在百度百科中,对于递归算法的定义是:某个函数直接或者间接地调用自身,这样原问题的求解就转换为了许多性质相同但是规模更小的子问题。

很多同学或许对这句话无法理解,没有关系。

在这里我们仅仅将其当作一个工具,在编写代码时,我们只需搞清楚繁杂的递归调用中的一次调用即可,不需要去深究他调用的过程。在文章后续的代码实现中,大家可以深刻体会到这句话的意思。

2.二叉树结点的创建

 既然是链式二叉树,对学习过链表的大家就很简单了。直接上代码

typedef char BTDataType;

typedef struct BTreeNode//每一个结点的结构
{
	BTreeNode* left;//指向左树
	BTreeNode* right; //指向右树
	BTDataType data;//结点的值
}BTNode;


BTNode* BuyNode(BTDataType x)//为新结点开辟空间
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	newnode->data = x;
	newnode->left = newnode->right = NULL;
	return newnode;
}

3.二叉树的遍历 

二叉树的遍历有四种:前序遍历、中序遍历、后序遍历、层序遍历。

今天我们在这里讲解前三种遍历,层序遍历请看下回分解。

3.1前序遍历

前序遍历就是先遍历根结点,在遍历左子树,最后遍历右子树。

理解了概念我们直接上代码。

void PreOrder(BTNode* root)//前序 根 左子树 右子树
{
	if (root == NULL)
	{
		printf("NULL");
		return;
	}
	else {
		printf("%c", root->data);//打印根节点
		PreOrder(root->left);//递归遍历左子树
		PreOrder(root->right);//递归遍历右子树
	}
}

这里我们就使用到了递归。该如何理解呢。

我们只关注一次调用,既然遍历左树,

那么我们就让根去找,即 PreOrder(root->left)。

遍历右树,即PreOrder(root->right)。

中间是如何进行调用的细节我们不需要深究,我们只需要知道这个递归的写法。剩下的交给计算机。如果大家仍没理解,可以画个对照代码画一个草图。

 

3.2中序遍历

中序遍历:先遍历左子树,在找根,最后遍历右子树。

代码如下

void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL");
		return;
	}
	else {
		
		InOrder(root->left);//遍历左树
		printf("%c", root->data);//找根
		InOrder(root->right);//遍历右树
	}
}

这里的递归我们仍然按一样的方法进行理解,只看一层调用。大家可以看图理解。 

3.3 后序遍历

后序遍历:先遍历左子树,再遍历右子树,最后找根。

void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL");
		return;
	}
	else {

		PostOrder(root->left);//遍历左树
		PostOrder(root->right);//遍历右树
		printf("%c", root->data);//找根
	}
}

后序的图大家就自己画画吧。 

4.统计二叉树的结点个数

 如何统计二叉树的结点个数呢。

思路很简单,没遍历一个非空结点,个数加一。我们看下面代码。

void TreeSize(BTNode* root)
{
	if (root == NULL)
		return;
	int count = 0;
	count++;//既然不为空,那么一定就有一个结点的存在
	TreeSize(root->left);
	TreeSize(root->right);
}

如果大家觉得这个代码对的话,那就掉入陷阱了!

在递归调用中,count存在于栈帧之中,并且递归的每一次调用都会开辟新的一块栈帧,这样的话我们的count就无法进行值的保存而达到连续的效果。所以这里我们不能这样进行实现。

下面我们介绍正确的写法。

void TreeSize(BTNode* root,int*p)//p为指向节点个数的指针
{
	if (root == NULL)
		return;
	++(*p);//结点个数++,既然不为空,那么一定有一个根结点,所以先++
	TreeSize(root->left, p);//遍历左子树的结点
	TreeSize(root->right, p);//遍历右子树的结点
}

我们在这里运用定义了一个外部指针变量,用来记录结点的个数,传入的是记录结点个数变量的地址。这样就可以避免 原来出现的问题了。

 其实这里还有个更加简单的方法,直接用root来记录结点个数。

int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

5.二叉树叶子结点的个数

 既然可以得到结点总数,那叶子结点是不是也可以得到呢。我们先上代码再解释。

int BTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL) //叶子结点的特点
	{
		return 1;
	}
	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);//找叶子结点
}

既然要找叶子结点首先我们要知道叶子结点的性质:左右子树均为空。

所以我们在递归的时候需要加入叶子结点的判断条件,如果是叶子结点就要返回。

当然在进行递归前要判断根节点是否存在或者根结点是否有值,我们将其划分为代码中的一中情况。

 6.二叉树第k层的结点个数

我们该如何求任意一层的结点个数呢。

我们将求第k层的结点个数转化为求第k-1层结点的左右子树个树是不是就和我们求叶子结点个数大同小异了呢!

int BTreeLayerSize(BTNode* root,int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BTreeLayerSize(root->left, k - 1) + BTreeLayerSize(root->right, k - 1);
}

我们加入需要的层数k,我们从根结点往下找第k层,如果要使其找到k层,就要使k=1。我们画图理解 。

我们假设要求第三层的结点个数,k=3。根结点为第一层,与其匹配的k=3,所以到找到第三层,就要使k--,简而言之,我们要找到的那一层匹配的k=1。这里可能有点绕,大家可以试着自己画图理解 。

 7.总结

 二叉树的内容到这里并没有结束,后序的内容需要用到队列的知识,所以我会在穿插队列的实现后继续为大家讲解二叉树的相关知识!敬请期待!

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

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

相关文章

activiti——网关配置

文章目录 前言网关介绍代码案例测试各项网关排他网关 ExclusiveGateway1、绘制流程图2、编写测试代码 并行网关ParallelGateway1、绘制流程图2、编写测试代码 包含网关InclusiveGateway1、绘制流程图2、编写测试代码 前言 在activiti工作流中,还有一个组件也很重要…

短视频拍摄+直播间搭建视觉艺术实战课:手把手场景演绎 从0-1短视频-8节课

抖音短视频和直播间你是否遇到这些问题? 短视频是用手机拍还是相机拍?画面怎么拍都没有质感 短视频产量低,拍的素材可用率低 看到别人用手机就能把短视频拍好自己却无从下手 明明已经打了好几盏灯了,但是画面还是比较暗 直播软件参数不会设置,电脑…

Git使用(1):介绍、克隆、推送

一、介绍与安装 1、Git是什么? Git是目前世界上最先进的分布式版本控制系统。工作原理 / 流程: workspace:工作区Index / Stage:暂存区Repository:仓库区(或本地仓库)Remote:远程仓…

3dmax材质库导入方法?3dmax云渲染速度体验

3ds Max 材质库包含多种素材,如金属、木材、布料和石材等,但用户在导入材质时常遇到问题。本文将介绍如何在3ds Max中成功导入材质,并探讨使用云渲染服务来加速渲染过程,提高项目效率。 一、3dmax材质库导入教程 自建材质导入方法…

LLM Agent智能体综述(万字长文)

前言 🏆🏆🏆在上一篇文章中,我们介绍了如何部署MetaGPT到本地,获取OpenAI API Key并配置其开发环境,并通过一个开发小组的多Agent案例感受了智能体的强大,在本文中,我们将对AI Agent…

卷积神经网络CNN的运行过程、常见术语与问题

目录 一、CNN运行过程 1、卷积(Convolution) 2、激活函数(activation function) 3、池化(pooling) 3.1 池化操作 3.2 池化过程 3.3 池化后结果 4、Flatten 5、全连接层 Flatten层的操作 全连接层…

Oracle 流stream将删除的数据保存

Oracle 流stream将删除的数据保存 --实验的目的是捕获hr.employees表的删除行,将删除行插入到emp_del表中。 --设置初始化参数 AQ_TM_PROCESSES1 COMPATIBLE9.2.0 LOG_PARALLELISM1 --查看数据库的名称,我的为ora9,将以下的ora9全部替换为你的数据库名称…

部分树上问题及图的联通性(图论学习总结部分内容)

文章目录 前言三、部分树上问题及图的联通性最小生成树知识点例题 e g 1 : eg1: eg1: 走廊泼水节(克鲁斯卡尔思想的灵活运用) e g 2 : eg2: eg2: B-Picnic Planning e g 3 eg3 eg3:L - Classic Problem&…

Mybatis入门之在基于Springboot的框架下拿到MySQL中数据

介绍 Java技术操作数据库 MyBatis是一款优秀的持久层框架 用于简化JDBC的开发 优秀的持久层框架 我们要基于Springboot整合Mybatis 实操 学习 基于Mybatis是如何操作数据库的 通过MyBatis书写SQL语句 SQL语句执行完毕后 会将查询结果返回给Java程序 表中数据会自动封装…

灵卡科技HDMI音视频采集及H.264编码一体化采集卡—LCC260

推荐一款由灵卡科技倾力打造的高品质HDMI音视频采集卡——LCC260。以创新的技术,精湛的工艺和卓越的性能,为您提供全方位的音视频解决方案。 LCC260是一款集HDMI音视频采集与H.264编码于一身的全功能采集卡。它的输入端配备了最先进的HDMI 1.4a标准接口&…

Vue实战技巧 —— 企业开发实战中的常见疑难问题

Vue企业开发实战中的常见疑难问题 1. 解决Vue动态路由参数变化,页面数据不更新2. vue组件里定时器销毁问题3. vue实现按需加载组件的两种方式4. 组件之间,父子组件之间的通信方案5. Vue中获取当前父元素,子元素,兄弟元素6. 开发环…

HIVE大数据平台SQL优化分享

相信很多小伙伴在面试的时候,必然跳不过去的一个问题就是SQL脚本的优化,这是很多面试官爱问的问题,也是可以证明你实力进阶的一个重要的能力。 下面给大家分享一个重量级的大数据行业sql技能---hive大数据平台SQL优化。 此文章是大数据平台…

Python中tkinter编程入门4

在Python中tkinter编程入门3-CSDN博客中创建了Button控件,点击该控件就会产生一个点击事件,在创建Button控件时指定该点击事件的处理程序后,按键控件就会对用户的点击事件产生响应。 1 定义事件处理器 定义事件处理器就是一个自定义的函数。…

【UnityRPG游戏制作】Unity_RPG项目_BOSS系统

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:就业…

使用Nginx对网站资源进行加密访问并限制访问IP

你好呀,我是赵兴晨,文科程序员。 大家在工作中有没有遇到过这样的需求,新上的网站部署到生产服务器上,但是还没公开,只允许个别高层领导看。 思来想去,我想到了一个简单的方法,通过Nginx对网站…

【Javaer学习Python】 1、Django安装

安装 Python 和 PyCharm 的方法就略过了,附一个有效激活PyCharm的链接:https://www.quanxiaoha.com/pycharm-pojie/pycharm-pojie-20241.html 1、安装Django # 安装Django pip install Django# 查看当前版本 python -m django --version 5.0.62、创建项…

SpringBoot项目的项目部署全过程

一、前端 安装nginx 1.将提前准备好的nginx的安装包上传到Linux中/opt目录下(我用的是Xftp) 2.解压 2.1:在xshell中解压该文件: tar -zxvf nginx-1.20.1.tar.gz 2.2:进入解压后的目录 cd nginx-1.20.1/ 2.3:安装需要的依赖 yum -y install zlib zlib-devel openssl openssl-de…

如何去掉试卷答案,并打印出来

实际上,针对试卷答案的问题,一个简单而高效的方法是使用图片编辑软件中的“消除笔”功能。只需将试卷拍摄成照片,然后通过这一功能,就可以轻松擦除答案。虽然这种方法可能需要一些时间和耐心,但它确实为我们提供了一个…

Kubernetes 群集部署

一、Kubernetes 概述 1.1、什么是 Kubernetes Kubernetes 是一个可移植、可扩展的开源容器编排系统,主要用于自动化部署、扩展和管理容器应用,提供资源调度、部署管理、服务发现、扩容缩容、监控等功能。对于负载均衡、服务发现、高可用、滚动升级、自…

【智能算法】河马优化算法(HO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年,MH Amiri受到自然界河马社会行为启发,提出了河马优化算法(Hippopotamus Optimization Algorithm, HO)。 2.算法原理 2.1算法思想 …