【C语言数据结构————————二叉树】

news2025/1/11 11:13:55

文章目录

  • 文章目录

  • 一、什么是树

    • 树的定义

    • 树的种类

    • 树的深度

    • 树的基本术语

  • 二、满二叉树

    • 定义

    • 满二叉树的特点

  • 三、完全二叉树

    • 定义

    • 特点

  • 四、二叉树的性质

  • 五、二叉树的存储结构

    • 顺序存储结构

    • 链式存储结构

  • 六、二叉树的基本操作 

  • 七、二叉树的创建

  • 八、二叉树的遍历

    • 前序遍历

    • 中序遍历

    • 后序遍历

  • 九、二叉树的销毁

  • 十、二叉树中节点的查找

欢迎阅读新一期的c语言数据结构模块————二叉树

✒️个人主页:-_Joker_-

🏷️专栏:C语言数据结构

📜代码仓库:c_code

🌹🌹欢迎大佬们的阅读和三连关注,顺着评论回访🌹🌹


一、什么是树

1.树的定义

树是n(n>=0)个结点的有限集。当n = 0时,称为空树。在任意一棵非空树中应满足:

  1. 有且仅有一个特定的称为根的结点。
  2. 当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中每个集合本身又是一棵树,并且称为根的子树。

2.树的种类

树的种类可以分为以下几种

  • 无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;
  • 有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;
  • 二叉树:每个节点最多含有两个子树的树称为二叉树;
  • 满二叉树:叶节点除外的所有节点均含有两个子树的树被称为满二叉树;
  • 完全二叉树:除最后一层外,所有层都是满节点,且最后一层缺右边连续节点的二叉树称为完全二叉树;
  • 哈夫曼树(最优二叉树):带权路径最短的二叉树称为哈夫曼树或最优二叉树。

3.树的深度

定义一棵树的根结点层次为1,其他结点的层次是其父节点层次加1。一棵树中所有结点的层次的最大值称为这棵树的深度。例如:

如图,图中的树的深度为:3 


4.树的基本术语

  • 结点的度:结点拥有的子树数目
  • 叶子(终端)结点:度为0的结点
  • 分支(非终端)结点:度不为0的结点
  • 树的度:树的各结点度的最大值
  • 内部结点:除根结点之外的分支结点
  • 双亲与孩子结点:结点的子树的根称为该结点的孩子;该结点称为孩子的双亲
  • 兄弟:属于同一双亲的孩子
  • 结点的祖先:从根到该结点所经分支上的所有结点
  • 结点的子孙:该结点为根的子树中的任一结点
  • 结点的层次:表示该结点在树中的相对位置。根为第一层,其他的结点依次下推;若
  • 结点在第L层上,则其孩子在第L+1层上
  • 兄弟节点:双亲在同一层的结点互为兄弟节点
  • 树的深(高)度:树中结点的最大层次
  • 有序树:树中各结点的子树从左至右是有次序的,不能互换。否则,称为无序树
  • 路径长度:从树中某结点Ni出发,能够“自上而下”通过树中结点到达结点Nj,则称Ni到Nj存在
  • 一条路径,路径长度等于这两个结点之间的分支数
  • 树的路径长度:从根到每个结点的路径长度之和。
  • 森林:是m(m≥0)棵互不相交的树的集合

由于二叉树的使用在数据结构中更加广泛,所以我们以二叉树为主来进行讲解,下面介绍一下关于二叉树的基本知识。


二、满二叉树

定义:

二叉树中,如果所有分支结点都存在左子树和右子树并且所有叶子节点都在同一层上,这样的二叉树称为满二叉树。

如图为一颗满二叉树

满二叉树的特点

满二叉树的特点有:

  1. 叶子节点只能出现在最下一层。
  2. 非叶子结点的度一定是2。
  3. 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
  4. 设树的深度为i,则总结点数为 2^i -1
  5. 满二叉树是一种特殊的完全二叉树
  6. 若有双亲,则其双亲为i / 2,若有左孩子,则左孩子为2i ,若有右孩子,则右孩子为2i + 1 。

三、完全二叉树

定义

对二叉树节点由左至右由上至下的编号,如果编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。

如图为一颗完全二叉树

特点
  1. 叶子结点只能出现在最下层和次下层。
  2. 最下层的叶子结点集中在树的左部。
  3. 倒数第二层若存在叶子结点,一定在右部连续位置。
  4. 如果结点度为1,则该结点只有左孩子,即没有右子树。
  5. 同样结点数目的二叉树,完全二叉树深度最小。
  6. 满二叉树一定是完全二叉树,但反过来不一定成立。

四、二叉树的性质

  • 二叉树的第i层上至多有2^(i-1) (i≥1)个结点
  • 深度为k的二叉树至多有2^k-1个结点(k≥1)
  • 对任何一棵二叉树T,如果其终端结点数为N0,度为2的结点数为N2,则N0=N2+1
  • 具有n个结点的完全二叉树的深度为[log2(n)]+1
  • 一棵具有n个结点的完全二叉树(又称顺序二叉树)对其结点按层从上至下(每层从左至右)进行1-n的编号,则对任一结点i(1≤i≤n)有:
  • 若i>1,则i的双亲是[i/2];若i=1,则i是根,无双亲。
  • 若2i≤n,则i的左孩子是2i;否则,i无左孩子
  • 若2i+1≤n,则i的右孩子是2i+1;否则,i无右孩子

五、二叉树的储存结构

二叉树的储存结构分为顺序存储结构和链式存储结构

顺序存储结构

二叉树的顺序存储是指用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为i ii的结点元素存储在一维数组下标为 i − 1的分量中。
依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映结点之间的逻辑关系,这样既能最大可能地节省存储空间,又能利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。
但对于一般的二叉树,为了让数组下标能反映二叉树中结点之间的逻辑关系,只能添加一些并不存在的空结点,让其每个结点与完全二叉树上的结点相对照,再存储到一维数组的相应分量中。然而,在最坏情况下,一个高度为h 且只有h 个结点的单支树却需要占据近2h-1个存储单元。二叉树的顺序存储结构如图所示,其中0表示并不存在的空结点。



链式存储结构

由于顺序储存结构非常不便,所以我们通常采用链式存储结构实现二叉树。链式存储结构通过开辟一块空间(节点),通过指针储存左孩子、右孩子节点以及数据。

由于顺序结构操作起来并不方便,所以我们通常都以链式存储结构通过递归来实现二叉树,定义如下

typedef struct BinaryTree
{
    int val;
    struct BinaryTree *left;
    struct BinaryTree *right;
}BT;

六、二叉树的基本操作

  • CreateTree() :创建二叉树
  • PreOrder(BT* root):二叉树的前序遍历
  • InOrder(BT* root): 二叉树的中序遍历
  • BackOrder(BT* root): 二叉树的后序遍历
  • DestoryTree(BT* root):销毁二叉树
  • FindTree(BT* root, int x):查找二叉树中值为x的节点

七、二叉树的创建

如下是对二叉树进行创建的算法

BTNode* CreatNode(int x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	node->val = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}

八、二叉树的遍历

前序遍历

二叉树的前序遍历顺序为根 - 左 - 右

即先访问根节点

然后访问其左孩子节点

最后访问其右孩子节点

例如上图,前序遍历顺序为:A -> B -> D -> E -> C -> F 

算法如下

void PreOrder(BT* root)
{
	if (root == NULL)
	{
		return;
	}
    printf("%d",root->val);
    PreOrder(root->left);
    PreOrder(root->right);
}

中序遍历

二叉树的前序遍历顺序为左 - 根 - 右

即先访问左孩子节点

然后访问其根节点

最后访问其右孩子节点

例如上图,前序遍历顺序为:D -> B -> E -> A -> F -> C 

算法如下

void InOrder(BT* root)
{
	if (root == NULL)
	{
		return;
	}
	InOrder(root->left);
	printf("%d ", root->val);
	InOrder(root->right);
}

后序遍历

二叉树的前序遍历顺序为左 - 右 - 根

即先访问左孩子节点

然后访问其根节点

最后访问其右孩子节点

例如上图,前序遍历顺序为:D -> E -> B -> F -> C -> A

 算法如下

void BackOrder(BT* root)
{
	if (root == NULL)
	{
		return;
	}
	BackOrder(root->left);
	BackOrder(root->right);
	printf("%d ", root->val);
}

九、二叉树的销毁

二叉树的销毁同样通过递归来实现:

void DestoryTree(BT* root)
{
	if (root == NULL)
	{
		return;
	}
	DestoryTree(root->left);
	DestoryTree(root->right);
	free(root);
}

十、二叉树中节点的查找

BT* FindTree(BT* root, int x)
{
	if (root == NULL)
	{
		return;
	}
	if (root->val == x)
		return root;
	FindTree(root->left, x);
	FindTree(root->right, x);
	return NULL;
}

以上就是对二叉树的介绍以及基本操作的实现,各位老爷别忘了给个支持三连🌹🌹

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

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

相关文章

Vue3 ref函数和active函数

一、ref函数 我们在setup函数中导出的属性和方法虽然能够在模板上展示出来,但是并没有给属性添加响应式,因此,我们需要使用ref函数来为我们的数据提供响应式。 (一)引入ref函数 import { ref } from "vue"…

pychon/PIL/opencv/json学习过程中遇到的问题

1. 使用PIL.Image读取图片 注意:pytorch中对图像预处理是transforms的输入必须是PIL格式的文件,使用cv2读取的图片就按照第二条的代码处理(3通道合并、归一化处理) from PIL import Image img Image.open("test1.jpg"…

计算机组成原理之概述

概述 计组主要讲的是计算机的硬件实现方式。 机器字长 比如8080处理器,如果想处理16位数的整数运算,就需要执行两次。 可见,机器字长会影响到数据的处理速度。 计算机硬件的基本组成 早期的冯诺依曼机 冯诺依曼提出了“存储程序”的概念&…

【数据分享】2021-2023年我国主要城市逐月轨道交通运营数据

以地铁为代表的轨道交通是大城市居民的主要交通出行方式之一,轨道交通的建设和运营情况也是一个城市发展水平的重要体现。本次我们为大家带来的是2021-2023年我国主要城市的逐月的轨道交通运营数据! 数据指标包括:运营线路条数(条…

网络编程 初探windows编程

目录 一、什么是Winodws编程 二、开发环境搭建以及如何学习 三、VA助手安装 四、第一个Win32程序 五、窗口类句柄/窗口类对象 六、Winodws消息循环机制 七、Windows数据类型 一、什么是Winodws编程 Windows 编程指的是在 Microsoft Windows 操作系统上进行软件开发的过…

答题猜歌闯关流量主小程序开发

视频互动答题是一款微信小程序游戏,以视频互动的形式进行答题,内容涵盖广泛,包括天文地理、生活百科、历史文化、综艺娱乐、数理知识等。 用户可以通过答题获得红包兑换余额,并有机会赢得豪华奖品。 设计风格:设计风格…

Halcon 练习(1):模板匹配

文章目录 前言相关视频链接模板匹配介绍Halcon平台使用动态区域截取代码优化固定选取位置添加打印信息添加匹配个数 个人能力不足 前言 Halcon平台的使用需要学习新的知识,这里专门开个新的专栏用来练习Halcon平台使用。 相关视频链接 WPF/HALCON机器视觉合集 模板…

基于51单片机DS18B20温度检测报警系统串口设置阀值-仿真及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20采集温度值送到数码管显示。 3、按键报警阀值或串口设置阀值。 4、测量温度小于下限或大于上限,蜂鸣器报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 uint z; …

MFC 简单绘图与文本编辑

目录 一.创建单文档项目 二.消息映射机制 三.WM_PAINT消息触发 四.CVIEW类 五.设备上下文 六.资源类和资源的关系 七.画线,矩形 八.画布 九.画笔 十.画刷 十一.利用TRACE打印日志 十二.文本编程 十三.ID号 十四.菜单栏 十五.菜单命令路由 十六.工具…

金蝶云星空将子窗体的内容传回到父窗体的开发实现

文章目录 金蝶云星空将子窗体的内容传回到父窗体的开发实现前置任务父窗体打开子窗体时传入回调函数子窗体设置返回参数父窗体接收参数在回调函数根据参数做一些逻辑处理 金蝶云星空将子窗体的内容传回到父窗体的开发实现 前置任务 金蝶云星空表单插件实现父窗体打开子窗体&a…

网络安全黑客技术自学

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防…

pytorch框架学习(tensorboard的使用)

什么是tensorboard? tensorboard是一个可视化工具,它可以把训练过程中的数据变化以图像的形式绘制出来,或者记录训练过程中使用的图片 tensorboard的安装: 在pycharm的终端中输出安装命令后自动安装—— pip install tensorbo…

BlendTree动画混合算法详解

【混合本质】 如果了解骨骼动画就知道,某一时刻角色的Pose是通过两个邻近关键帧依次对所有骨骼插值而来,换句话说就是由两个关键帧混合而来。 那么可不可以由多个关键帧混合而来呢?当然可以。 更多的关键帧可以来自不同的动画片段&#xf…

【MySQL】事务(中)

文章目录 事务异常与产出结论手动提交 和自动提交 对 回滚的区别 事务隔离性理论如何理解隔离性?MySQL的隔离级别事务隔离级别的查看设置隔离级别 事务异常与产出结论 在没有启动事务之前,account表中存在孙权和刘备的数据 在启动事务后, 向 …

通过 Kaptcha 插件生成字符验证码

Kaptcha 是 Google 的⼀个⾼度可配置的实⽤验证码⽣成⼯具,我们选择的是⼀个适配SpringBoot的 开源项⽬ 生成的验证码效果如下: 原理 验证码可以客户端生成,也可以服务器生成. 对于普通的字符验证码, 后端通常分两部分: ⼀:⽣成验…

C语言求数组中出现次数最多的元素

一、前言 遇到一个需求,需要求数组中出现次数最多的元素,查找了一些资料,结合自己的思路,编写了程序并验证。 只考虑元素为非负整数的数组,如果有出现次数相同的元素,则返回较小元素。 二、编程思路 以数…

原生JS实现视频截图

视频截图效果预览 利用Canvas进行截图 要用原生js实现视频截图,可以利用canvas的绘图功能 ctx.drawImage,只需要获取到视频标签,就可以通过drawImage把视频当前帧图像绘制在canvas画布上。 const video document.querySelector(video) con…

若依系统富文本框上传图片报错!

报错如下: 原因:如图,富文本路径中存在 / 字符,导致上传出错。 解决方案:将富文本框内容在前端进行加密,后端再解密。 前端: 安装 crypto-js 插件 npm install crypto-js 创建工具类 :在 sr…

postswigger 靶场(CSRF)攻略-- 1.没有防御措施的 CSRF 漏洞

靶场地址: What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy (portswigger.net)https://portswigger.net/web-security/csrf 没有防御措施的 CSRF 漏洞 题目中已告知易受攻击的是电子邮件的更改功能,而目…