数据结构之树 --- 二叉树

目录

定义二叉树的结构体

二叉树的遍历

递归遍历

非递归遍历 

链式二叉树的实现 

二叉树的功能接口

先序遍历创建二叉树

后序遍历销毁二叉树 

 先序遍历查找树中值为x的节点

层序遍历


上篇我们对二叉树的顺序存储堆进行了讲述,本文我们来看链式二叉树。

定义二叉树的结构体

定义链式二叉树同定义链表相同,只是需要注意二叉树有两个指针,类似于双向链表,逻辑上我们将其看作一棵二叉树。下面是定义该树的结构体。

typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;

在创建二叉树之前,我们需要了解前序、中序、后序以及层序遍历。

二叉树的遍历

递归遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLRLNRLRN分别又称为先根遍历、中根遍历和后根遍历。

下图展示先序遍历的递归结构:

非递归遍历 

非递归遍历也即层序遍历:

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

图示: 

链式二叉树的实现 

二叉树的功能接口

数据结构的实现无非是增删查改,二叉树也不例外。

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTNode* root, BTDataType* str);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);层序遍历
//void BinaryTreeLevelOrder(BTNode* root);判断二叉树是否是完全二叉树
//bool BinaryTreeComplete(BTNode* root);

先序遍历创建二叉树

先序遍历创建一个二叉树,我们递归遍历每个元素,然后为其创建节点,但叶子节点没有孩子怎么办?

叶子节点没有孩子,因此当递归到叶子节点的孩子时需要返回NULL;我们需要在需要创建的元素数组中做好标记,比如下面这个代码,当我们遇到 '#' 时返回NULL结束函数,不创建节点。

通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
struct BTNode* PreorderCreate(int* a,int* i)
{if (a[*i] == '#'){(*i)++;return NULL;}struct BTNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));root->val = a[*i];(*i)++;root->left = PreorderCreate(a, i);root->right = PreorderCreate(a, i);return root;
}

后序遍历销毁二叉树 

销毁一个二叉树,我们设想一下,当销毁了树的根节点,那么我们就找不到他的孩子了。因此根节点必然是最后一个销毁的,所以我们用后序遍历来销毁二叉树。

我们递归遍历最深的节点,依次往上销毁。

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

 先序遍历查找树中值为x的节点

树的查找,这里我们以先序遍历为例。

若该节点数据等于x,则返回该节点。否则递归其孩子,我们分别用ret1与ret2记录递归其左右孩子的返回值,然后判断返回值是否存在。根据函数可知,函数的返回只可能为NULL或者是值为x的节点。

至于我们为什么要使用ret1、ret2,那是因为如果直接用 BinaryTreeFind(root->left, x);来判断的话,我们会再次进入这个节点的递归,造成额外的栈帧负担。

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->data == 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;
}

层序遍历

层序遍历为非递归遍历,对于树而言,非递归往往更难。

这里我们借用队列来实现树的层序遍历,关于队列实现层序遍历,我们后面再讲。

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);while (QueueEmpty(&q)){if (!root)QueuePush(&q, root);BTNode* tmp = QueueFront(&q);QueuePop(&q);printf("%d ", tmp->data);if (!root->left)QueuePush(&q, root->left);if (root->right)QueuePush(&q, root->right);}	
}

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

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

相关文章

SpringCloud(H版alibaba)框架开发教程之nacos做配置中心——附源码(2)

上篇主要讲了使用eureka,zk,nacos当注册中心 这篇内容是nacos配置中心 代码改动部分mysql驱动更新到8.0,数据库版本升级到了8.0,nacos版本更新到了2.x nacos2.x链接 链接:https://pan.baidu.com/s/11nObzgTjWisAfOp…

探秘交互设计:深入了解五大核心维度!

交互式设计是用户体验(UX)设计的重要组成部分。本文将解释什么是交互设计,并分享一些有用的交互设计模型,并简要描述交互设计师通常做什么。 如何解释交互设计 交互式设计可以用一个简单的术语来理解:它是用户和产品…

借贷协议 Tonka Finance:铭文资产流动性的新破局者

“Tonka Finance 是铭文赛道中首个借贷协议,它正在为铭文资产赋予捕获流动性的能力,并为其构建全新的金融场景。” 在 2023 年的 1 月,比特币 Ordinals 协议被推出后,包括 BRC20,Ordinals 等在内的系列铭文资产在包括比…

nginx源码分析-3

这一章内容讲述nginx中的事件是如何一步步添加到epoll实例中的。 在初始化http连接的函数ngx_http_init_connection中,nginx为http连接初始化了处理请求的回调函数,之后调用ngx_handle_read_event函数对可读数据进行处理。这里只为连接设置read而没有设…

Ubuntu22.04 安装教程

系统下载 Ubuntu官网下载 清华源镜像 安装流程 1. 选择安装语言 2. 选择是否在安装时更新 为了系统安装速度一般选择安装时不更新,安装后自行更新 3. 选择系统语言和键盘布局 4. 选择安装模式 5. 配置网络信息 6. 设置静态IP 7. 配置代理信息 8. 配置Ubuntu镜像…

在电脑上免费分区的 5 个有效磁盘分区软件工具

磁盘分区可能是一个脆弱而复杂的过程,磁盘崩溃或用户设备受到病毒攻击的风险很高。因此,它们很难由用户单独或手动管理。本文详细介绍了可以帮助简化磁盘分区过程的不同软件工具、它们的功能和优点。那么让我们开始吧。 什么是磁盘分区工具? …

在STM32中集成TSL2561光强传感器的开发和调试

在STM32中集成TSL2561光强传感器的开发和调试是一个常见的应用场景。TSL2561是一款数字光传感器,能够测量可见光和红外光的光强,并通过I2C接口将数据传输给微控制器。下面将为您介绍在STM32中集成TSL2561传感器的开发步骤,并附上相应的代码示…

【音视频 ffmpeg 学习】 RTMP推流 mp4文件

1.RTMP(实时消息传输协议)是Adobe 公司开发的一个基于TCP的应用层协议。 2.RTMP协议中基本的数据单元称为消息(Message)。 3.当RTMP协议在互联网中传输数据的时候,消息会被拆分成更小的单元,称为消息块(Chunk&#xff…

Linux系统下隧道代理HTTP

在Linux系统下配置隧道代理HTTP是一个涉及网络技术的话题,主要目的是在客户端和服务器之间建立一个安全的通信通道。下面将详细解释如何进行配置。 一、了解基本概念 在开始之前,需要了解几个关键概念:代理服务器、隧道代理和HTTP协议。代理…

算法专题四:前缀和

前缀和 一.一维前缀和(模板):1.思路一:暴力解法2.思路二:前缀和思路 二. 二维前缀和(模板):1.思路一:构造前缀和数组 三.寻找数组的中心下标:1.思路一:前缀和 四.除自身以外数组的乘积&#xff…

3、Git分支操作与团队协作

Git分支操作 1.什么是分支2. 分支的好处3. 分支的操作3.1 查看分支3.2 创建分支3.3 切换分支3.4 修改分支3.5 合并分支3.6 产生和解决冲突 4. 创建分支和切换分支图解5. Git团队协作机制团队内协作跨团队协作 均在git bash中进行操作。事先建好本地工作库 1.什么是分支 在版本…

GLTF 编辑器实现逼真3D动物毛发效果

在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 要实现逼真的3D动物毛发效果,可以采用以下技术和方法&…

Vue学习day_03

普通组件的注册 局部注册: 创建一个components的文件夹 在里面写上对应的.vue文件 在对应的vue里面写上对应的3部分 template写上对应的核心代码 盒子等 style 写上对应的css修饰 在App.vue里面进行引用 import 导包 格式是 import 起个名字 from 位置 在写一个component…

3d导入模型怎样显示原本材质---模大狮模型网

要在导入3D模型时保留原本的材质,您可以尝试以下方法: 导入前检查文件格式:确保您所使用的3D软件支持导入模型的文件格式。不同的软件对文件格式的支持有所差异,选择正确的文件格式可以更好地保留原始材质。 使用正确的材质库&am…

【Python篇】python库讲解(wordcloud | jieba)

文章目录 🍔jieba库🍔wordcloud库🌹解释 🍔jieba库 jieba库是一个流行的中文分词工具,它基于统计算法和词频字典,能够将连续的汉字序列切割成有意义的词语。下面是对jieba库的简要理论说明: 分…

复数值神经网络可能是深度学习的未来

一、说明 复数这种东西,在人的头脑中似乎抽象、似乎复杂,然而,对于计算机来说,一点也不抽象,不复杂,那么,将复数概念推广到神经网络会是什么结果呢?本篇介绍国外的一些同行的尝试实践,请我们注意观察他们的进展。

【机组期末速成】指令系统|机器指令概述|操作数类型与操作类型|寻址方式|指令格式

🎥 个人主页:深鱼~🔥收录专栏:计算机组成原理🌄欢迎 👍点赞✍评论⭐收藏 目录 前言: 一、本章考点总览 二、考点分析 1、以下有关指令系统的说法中错误的是( )。 2…

idea远程开发环境搭建

idea远程开发环境搭建 一、安装包下载二、环境准备2.1服务器端jdk、maven安装,代码下载略2.2JetBrainsClients下载配置 三、远程环境配置3.1 创建项目3.2 填写服务器连接信息![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/4aa09073af5e4a66a5e83e7c5d1…

Unity 通过鼠标框选绘制矩形区域

鼠标拖动的同时绘制一块同等大小的区域&#xff1a;如下 using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 通过鼠标框选绘制矩形区域 /// </summary> /// public enum MouseType {left 0,right 1,middle 2 …

MySQL线上慢SQL问题分析处理小记

相同数据量表结构&#xff0c;线上执行12s 本地执行0.1s过程分析 1. 慢SQL信息 SELECT t1.id,t2.idFROM t_platform_target_standard_target_index t1LEFT JOIN t_platform_target_standard t2 ON t1.target_number t2.target_numberWHERE t1.delete_flag 0 AND t2.user_num …