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

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

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.mzph.cn/diannao/12269.shtml

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

相关文章

鸿蒙ArkUI开发:常用布局【相对布局】

相对布局(RelativeContainer) 相对布局可以让子元素指定兄弟元素或父容器作为锚点,基于锚点做位置布局必须为RelativeContainer及其子元素设置ID,用于指定锚点信息。未设置ID的子元素不会显示RelativeContainer ID为“__containe…

增程SUV价格即将崩盘?买车一定要再等等!

文 | AUTO芯球 作者 | 雷歌​ 真是“离谱”啊,车圈真是逗比欢乐多, 我这两天看一个博主连续40多小时开车直播,充电口、油箱盖全部封死,全程视频直播没断过, 就为了测试这两天刚上市的星际元ET续航有多远。 另一个…

NSSCTF Web方向的例题和相关知识点(二)

[SWPUCTF 2021 新生赛]Do_you_know_http 解题: 点击打开环境,是 提示说请使用wLLm浏览器访问 我们可以更改浏览器信息,在burp重放器中发包后发现是302重定向,但是提示说success成功,说明 我们修改是成功的&#xff…

HTML特殊字符

特殊字符 有特殊含义的字符成为字符实体 对于有特殊含义的字符,需要通过转移字符来表示 <span> <br><a href"http://www.atguigu.com">我 爱 前端</a> <br>&amp;amp; 效果

Element-UI 快速入门指南

文章目录 一、安装 Element-UI1.1 使用 npm 安装1.2 使用 yarn 安装 二、引入 Element-UI三、使用 Element-UI 组件3.1 按钮组件3.2 输入框组件3.3 表单组件3.4 表格组件3.5 弹框组件 四、自定义主题4.1 安装主题工具4.2 初始化变量文件4.3 编译主题 五、总结 &#x1f389;欢迎…

刷题之最长连续序列

哈希表 class Solution { public:int longestConsecutive(vector<int>& nums) {//set记录并且去重nums中的数unordered_set<int>set;for(int i0;i<nums.size();i){set.insert(nums[i]);}int result0;//遍历所有数for(auto iset.begin();i!set.end();i){//如…

服务的war包已经丢在tomcat中但是还是没法访问,如何排查?

问题出现的现象是我已经将 XWiki 的 WAR 包放置在 Tomcat 的 webapps目录下但仍然无法访问&#xff0c;反思之后可以从下面以下几个方面来诊断和解决问题&#xff1a; 1. 确认 Tomcat 正在运行 首先&#xff0c;确保 Tomcat 服务正在正常运行。可以使用以下命令检查 Tomcat 的…

鉴源论坛·观通丨轨交软件测试技术详述

作者 | 刘艳青 上海控安安全测评部测试经理 版块 | 鉴源论坛 观通 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 集成测试技术要求 1.1 总体要求 对软件集成测试进行静态测试应先于动态测试&#xff1b; 集成过程是动态进行的&#xff0c;在测…

CVHub | CVPR 2024 | 英伟达发布新一代视觉基础模型: AM-RADIO = CLIP + DINOv2 + SAM

本文来源公众号“CVHub”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;CVPR 2024 | 英伟达发布新一代视觉基础模型: AM-RADIO CLIP DINOv2 SAM 标题&#xff1a;《AM-RADIO: Agglomerative Vision Foundation Model Reduce Al…

vscode 之 output 输出中文乱码,终端输出中文正常

# 1. 背景 因为没钱买正版的软件&#xff0c;所以转战 vscode 编译器。 在编译 python 文件时&#xff0c;发现直接右键 runner code&#xff0c;输出中文乱码。 但是在 teiminal 终端 执行py test.py 时&#xff0c;输出正常&#xff0c;中文正常。 output 输出中文样式(中文…

Go微服务: Prometheus性能监控与Grafana平台的搭建

Prometheus 概述 promethues 是一套开源的监控&报警&时间序列数据库的组合基本原理是通过http协议周期性抓取被监控组件的状态适合Docker、Kubernetes环境的监控系统 Promethues 整体架构 一、抓取数据的两种方式 1 &#xff09;Short-lived jobs 短暂的任务 不会提…

RedisTemplate操作Redis详解之连接Redis及自定义序列化

连接到Redis 使用Redis和Spring时的首要任务之一是通过IoC容器连接到Redis。为此&#xff0c;需要java连接器&#xff08;或绑定&#xff09;。无论选择哪种库&#xff0c;你都只需要使用一组Spring Data Redis API&#xff08;在所有连接器中行为一致&#xff09;&#xff1a;…

面对.halo勒索病毒,如何有效防范与应对?

导言&#xff1a; 随着网络技术的不断发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;勒索病毒作为一种极具破坏性的网络攻击手段&#xff0c;近年来在全球范围内频发。其中&#xff0c;.halo勒索病毒作为勒索病毒家族中的一员&#xff0c;其危害性和传播性不容忽视…

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读 Abstract1 Introduction2 Related Work3 Proposed Approach4 Experiments5 Conclusion 文章信息&#xff1a; 原文链接&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/4…

二叉树专题(有关二叉树的相关学习)

二叉树 1.数概念及结构 1.1树的结构 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结…

ollama离线部署llama3(window系统)

首先介绍下ollama是什么&#xff1f;Ollama是一个开源的大型语言模型服务工具&#xff0c;旨在为用户提供本地化的运行环境&#xff0c;满足个性化的需求。具体来说&#xff0c;Ollama是一个功能强大的开源框架&#xff0c;可以简化在Docker容器中部署和管理大型语言模型&a…

【C++】内联函数、auto、范围for

文章目录 1.内联函数2.auto关键字2.1auto简介2.2auto的注意事项2.3auto不能推导的场景 3.基于范围的for循环(C11)4.指针空值nullptr(C11) 1.内联函数 概念&#xff1a; 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函…

商场综合体能源监管平台,实现能源高效管理

商场作为大型综合体建筑&#xff0c;其能源消耗一直是备受关注的问题。为了有效管理商场能耗&#xff0c;提高商场能源效率&#xff0c;商场综合体能源监管平台应运而生。 商场综合体能源监管平台可通过软硬件一起进行节能监管&#xff0c;硬件设备包括各种传感器、监测仪表和…

Matter 1.3版标准新出炉,支持更多智能家居/家电/能源等设备

5月8日&#xff0c;CSA连接标准联盟正式发布了Matter 1.3标准&#xff0c;过去CSA一直保持约每六个月一次的标准更新节奏。 图源CSA连接标准联盟官方 获得一系列改进的Matter 1.3标准&#xff0c;将提升设备的互操作性&#xff0c;扩展支持的设备类别&#xff0c;并增强整个智…

Android 几种系统升级方式详解

目录 ◆ 概述 ● 几种启动模式 ● MISC分区 ● CACHE分区 ● 几种系统升级方式 ◆ Recovery升级 ● 升级包构成&#xff0c;签名&#xff0c;制作 ● 升级脚本 ● 升级过程 ◆ OTA升级 ● 升级包构成&#xff0c;制作 ● 升级脚本 ● 升级过程 ◆ fastboot升级 ◆ ADB升级 几…