DS:数与二叉树的相关概念

欢迎来到Harper.Lee的学习世界!
博主主页传送门:Harper.Lee的博客主页
想要一起进步的uu可以来后台找我哦!

一、树的概念及其结构

1.1 树的概念+亲缘关系

          树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

要点:

1. 有一个特殊的节点,称为根节点,根节点没有前驱节点。
2. 除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。(每个孩子只能有一个父亲,一个父亲可以有多个孩子)。
3. 因此,树是递归定义的。

        任何一棵树都包含了根和N棵子树(N>=0),子树又由新的根和子树组成;N=0时,该树被称为空树。就像递归一样,将大问题逐步拆解成一个个不可再拆解的小问题。(很形象的描述就是,递归其实是套娃🪆)
        注意:在树形结构中,子树之间不能有交集,否则就不是树结构了!!!(子树之间相交叫做图)

1.2 树的相关名词

        树是由根和子树构成的,也可以说是分支节点和叶子节点构成的。我们可以根据树+人类亲缘关系来定义解读树的相关名词。

名词

意义

上图中表示

节点的度

一个节点含有的子树的个数

A节点的度为6

叶节点或终端节点

度为0的节点

B、C、H、I、P、Q、K、L、M、N节点称为叶节点

非终端节点或分支节点

度不为0的节点

A、D、E、F、G、J节点为分支结点

双亲节点或父节点

若一个节点 含有子节点,则这个节点称为其子节点的父节点

A是B的父节点

孩子节点或子节点

一个节点含有的子树的根节点称为该节点的节点

B是A的孩子节点

兄弟节点

具有相同父节点的节点(相当于是亲兄弟)互称为兄弟节点

B、C是兄弟节点

树的度

一棵树中,最大的节点的度称为树的度

因为A节点的度为最大的度,所以树的度为6

节点的层次(Level)

从根开始定义起,根为第1层,根的孩子为第2层,以此类推,就相当于楼层;树中节点的最大层次称为树的深度(Depth)或高度

上图节点的层次为4(相当于4层楼)

树的高度或深度

树中节点的最大层次,相当于最大楼层数

上图中树的最大高度为4

堂兄弟节点

双亲在同一层的节点互为堂兄弟(相当于不是同一个双亲)

上图H、I互为堂兄弟节点

节点的祖先

从根到该节点所经分支上的所有节点(简而言之,祖先都是一条线上的蚂蚱🦗)

上图中A是所有节点的祖先

子孙

以某结点为根的子树中任一节点都称为该节点的子孙

上图中所有节点都是A的子孙

森林

由m(m>0)棵互不相交的树的集合称为森林(森林是一群树)

上图是单独一棵树,不能构成森林

        深入讨论:

a. 为什么根节点的层次是从第1层开始定义的,而非第0层?
        现有一棵树没有子树,那么如果从1开始定义,那么根节点的高度为0;如果从0开始定义,那么根节点的高度为-1。
b. 那么为什么C语言中的数组下标从0开始呢?
        因为数组的下标从0开始,便于计算。数组名是数组首元素的地址。例如arr[i]等价于*(arr+i)。而如果数组的下标从1开始,那么arr[i]代表第i个元素,而*(arr+i)代表第i+1个元素,二者不再等价。

1.3 树的表示方法

        树的结构相比较于以往的其他结构就比较复杂了,要存储起来表示就比较有难度,不仅要保存值域,也要保存节点和节点之间的关系。实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。

1.3.1 已知节点的度

        如果已知节点的度,那么就可以根据这个度来确定树的结构体中需要孩子指针的数量。

//明确树的高度为N(树的度:一棵树中, 含有的子树个数最大的节点称为树的度)
typedef int DataType;
struct TreeNode
{DataType val;struct TreeNode* subs[N];//定义了一个指针数组
};

1.3.2 未知节点的度

        如果不知道节点的度,那么我们就需要另寻他法来定义树结构。下面就是常用的定义表示法。

(1)双亲表示法

        双亲表示法的基本思想:用一维数组来存储树的各个节点(一般按层序存储),数组中的一个元素对应树中的一个节点,包括节点的数据信息以及该节点的双亲在数组中的下标。

//双亲表示法
typedef int DataType;
struct PNode
{DataType data;  //数据域int parent;		//指针域,双亲在数组中的下标(即用整型来表示父亲节点的位置)
};

        树的双亲表示法实质上是一个静态链表。当算法中需要在树结构中频繁地查找某节点的父节点时,使用双亲表示法最合适。当频繁地访问节点的孩子节点时,双亲表示法就很麻烦,采用孩子表示法就很简单。

(2)孩子链表表示法

        孩子链表的表示方法:链表中的每个节点包括一个数据域和多个指针域,每个指针域指向该节点的一个孩子节点。

        其中,data:数据域,存放该节点的数据信息;

        child1~childn:指针域,指向该节点的孩子。

        孩子链表的基本思想:把每个节点的孩子排列起来,看成是一个线性表,且以单链表存储,则n个节点共有n个孩子链表。这n个单链表共有 n个头指针,一起组成一个线性表,为了便于进行查找采用顺序存储。最后,将存放n个头指针的数组和存放n个节点的数组结合起来,构成了孩子链表的表头数组。

        使用孩子表示法存储的树结构,正好和双亲表示法相反适用于查找某节点的孩子节点,不适于查找其父节点 。可以将两种方法合二为一。(博客园--gonghr)

(3)双亲孩子表示法

(4)左孩子右兄弟表示法

        左孩子右兄弟表示法是是我们经常用的一种方法。无论一个父亲节点有多少个孩子,leftChild都指向左边开始的第一个孩子节点。rightBrother指向同一层的兄弟,而且这个兄弟是同样的父母(相当于leftChild是双亲带大的第一个孩子即老大,剩下的孩子老二老三等就有老大带大)关系图如下:

//左孩子右兄弟表示法
typedef int DataType;;
struct TreeNode
{DataType val;//节点中的数据域struct TreeNode* firstChild;//左边孩子指针(第一个孩子节点)struct TreeNode* pNextBrother;//右边兄弟指针(指向下一个兄弟节点)
};

        既然已经定义好了树的结构,那现在应该如何通过左孩子右兄弟找到所有的孩子节点?示例代码如下:

//通过左孩子右兄弟找到所有的孩子节点:
struct TreeNode* parent;//定义树的结构体指针
struct TreeNode* cur = parent->leftChild;while (cur)
{//……cur = cur->rightBrother;
}

1.4 树的相关应用

(1)文件系统中的目录树结构就是经典的树结构。

        我们打开磁盘,在底层就是通过磁盘的孩子指针找到第一个孩子,再通过第一个孩子的兄弟指针开始逐个遍历后面的兄弟节点,才能把整个目录给列举出来。

        如果我们新建一个文件夹,就是让该文件目录下的兄弟节点指向NULL的文件指向这个新建文件,然后新建文件的兄弟指针指向NULL,当然这个也要看情况,有时候文件排序的方式也是不同的

(2)Linux树状目录结构

二、二叉树的概念及其结构

        在所有的树的相关结构中,二叉树是我们经常用的一种结构。

2.1 二叉树概念

        一棵二叉树是节点的一个有限集合,该集合的特点是:1. 要么为空;2. 要么由一个根节点加上两棵别称为左子树和右子树的二叉树组成。

        二叉树的特点:a. 二叉树的度最大为2(相当于对其进行了计划生育,最多生育2个孩子);b. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。

        注意:对于任意的二叉树都是由以下几种情况复合而成的:

2.2 特殊的二叉树

        1. 满二叉树:一个二叉树,如果每一个层的节点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且节点总数是2k-1 ,则它就是满二叉树。

        2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。(简言之,完全二叉树的最后一层不是满的)

2.3 二叉树的性质

1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2(i-1)个结点。

2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2h-1。

(ps:20层满二叉树,节点数为100W+;30层满二叉树,节点数为10亿+)

3. 对任何一棵二叉树, 如果度为0其叶结点个数为 n0, 度为2的分支结点个数为n2 ,则有n0 =n2 +1。

4. 若规定根结点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1)。

5. 对于具有 n 个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对于序号为 i 的结点有:

        a. 若i>0,i位置结点的双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点;

        b. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子;

        c. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子。

2.4 二叉树的存储结构

        二叉树一般可以使用两种结构存储,一种是顺序结构存储,一种是链式结构存储

2.4.1 顺序存储

        顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。

二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树。分析过程如下:

        一般来说,顺序存储只适用于完全二叉树(满二叉树是特殊的完全二叉树)! 

2.4.2  链式存储

         二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链。

        


喜欢的uu三连支持一下嗷!

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

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

相关文章

Marvelous Designer中一些棉质布料预设

Marvelous Designer中一些棉质布料预设的解释&#xff1a; Cotton_14_Wale_Corduroy&#xff1a;14条细鲸鱼纹的灯芯绒&#xff0c;适合制作温暖且有质感的服装。Cotton_40s_Chambray&#xff1a;40支精梳针织的府绸布&#xff0c;通常用于制作休闲衬衫。Cotton_40s_Poplin&am…

Face Forgery Detection by 3D Decomposition

文章目录 Face Forgery Detection by 3D Decomposition研究背景研究目标创新点方法提出问题研究过程技术贡献实验结果未来工作Face Forgery Detection by 3D Decomposition 会议:CVPR2021 作者: 研究背景 面部伪造引发关注传统面部伪造检测主要关注原始RGB图像

学Python,看一篇就够

学Python&#xff0c;看一篇就够 python基础注释变量标识符命名规则使用变量认识bugDebug工具打断点 数据类型输出转义字符输入输入语法输入的特点 转换数据类型pycharm交互运算符的分类赋值运算符复合赋值运算符比较运算符逻辑运算符拓展 条件语句单分支语法多分支语法拓展 if…

XFF注入【墨者靶场】

目录 XFF介绍 靶场练习 最近在复习XFF注入&#xff0c;这里使用墨者靶场来简单的练习一下该漏洞的利用方法 XFF介绍 X-Forwarded-For&#xff1a;简称XFF头&#xff0c;代表了HTTP的请求端真实的IP。 它被认为是客户端通过HTTP代理或者负载均衡器连接到web服务端获取源ip地…

植物大战僵尸杂交版2.0.88最新版安装包

游戏简介 游戏中独特的杂交植物更是为游戏增添了不少亮点。这些杂交植物不仅外观独特&#xff0c;而且拥有更强大的能力&#xff0c;能够帮助玩家更好地应对游戏中的挑战。玩家可以通过一定的条件和方式&#xff0c;解锁并培养这些杂交植物&#xff0c;从而不断提升自己的战斗…

打开C# 大门:Hallo, World!

C# 介绍 C#&#xff08;C Sharp&#xff09;是一种面向对象的编程语言&#xff0c;由微软公司开发。它是 .NET Framework 的一部分&#xff0c;用于构建 Windows 应用程序、Web 应用程序、移动应用程序等。C# 语言的设计目标是简单、现代化、易于学习和使用。在本文中&#xf…

量化交易:Miniqmt获取可转债数据和交易python代码

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 低风险资产除了国债外&#xff0c;还有可转债&#xff0c;兼容有高收益的股性和低风险的债性&#xff0c;号称“下有保底&#xff0c;上不封顶”。 &#x1f50d; 可转债&#xff1a;金融市场的双面娇娃 可转债&am…

python篮球队员招募 2024年3月青少年编程电子学会python编程等级考试二级真题解析

目录 python篮球队员招募 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python篮球队员招募 2024年3月 python编程等级考试级编程题 一、题目…

apsw,一个超强的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超强的 Python 库 - apsw。 Github地址&#xff1a;https://github.com/rogerbinns/apsw 在现代应用开发中&#xff0c;数据库是一个非常重要的组成部分。SQLite 是一个轻量级的嵌入式关系数据…

斯坦福AI团队抄袭事件,清华回应:也算国际认可

近日&#xff0c;斯坦福大学人工智能&#xff08;AI&#xff09;团队的一项备受瞩目的研究——Llama3-V大模型&#xff0c;陷入了抄袭风波。该团队原本以其创新的模型和低廉的训练成本为亮点&#xff0c;声称能够在低成本下训练出性能卓越的SOTA多模态大模型。然而&#xff0c;…

Redis实战篇——搭建主从复制

Redis实战篇——搭建主从复制 1.Redis主从1.1.主从集群结构1.2.搭建主从集群1.2.1.启动多个Redis实例1.2.2.建立集群1.2.3.测试 1.Redis主从 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离…

HR在线人才测评,如何判断候选人的学习能力?

在选拔人才的过程中&#xff0c;学习能力突出的候选人&#xff0c;能以非常快的速度适应工作环境&#xff0c;并且会在工作当中制定清晰的学习规划&#xff0c;不断的提升自己&#xff0c;不断的彰显个人在企业当中的价值&#xff0c;助力企业的长远发展。 只有选拔进来的人才…

python中实现队列功能

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 python中实现队列功能 选择题 以下代码最后一次输出的结果是&#xff1f; from collections import deque queue deque() queue.append(1) queue.append(2) queue.append(3) print(【显示】…

QT c++ 堆栈一些理解--限制对象建立在栈上--栈堆区别

图示形象化理解&#xff1a; 堆栈都是数据结构存取数据的方式 堆&#xff1a;理解为一个堆积物体&#xff0c;独立的分散的&#xff0c;当需要空间时&#xff0c;再找一个地方。需要的就是new关键字&#xff0c;动态申请一个空间。程序员自己动态分配空间&#xff0c;使用指针…

【Git教程】(二十一)与其他版本控制系统并行使用 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

Git教程 与其他版本控制系统并行使用 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 初始部署版本库3.2 得到中央版本控制管理中的更新修改3.3 将修改提交传输到中央本版控制系统 在许多企业和组织中&#xff0c;会统一管理版本控制工具和相关的流程。其中的个人和小团队…

[Linux] 软链接使用绝对路径的重要性

文章目录 软链接使用绝对路径的重要性软链接路径复制软链接查看文件类型 软链接使用绝对路径的重要性 软链接路径 软链接必须指定绝对路径&#xff0c;否则复制软链接后&#xff0c;由于软链接的相对路径是从软链接所处位置开始解析的&#xff0c;因此使用相对路径的软链接可…

【代码随想录——贪心算法——四周目】

1.用最少数量的箭引爆气球 func findMinArrowShots(points [][]int) int {n : len(points)sort.Slice(points, func(i, j int) bool {if points[i][0] ! points[j][0] {return points[i][0] < points[j][0]} else {return points[i][1] < points[j][1]}})cover : points[…

Kotlin 网络请求小例子(Ktor)

文章目录 导入依赖创建 Http 客户端 其实还是借着 Ktor 学一学 Kotlin 如何导入依赖&#xff0c;这应该是我们 Kotlin 基础专栏的最后一期了。 Ktor 是 Kotlin 官方的一个网络请求库&#xff0c;它具有优秀且精炼的 API&#xff0c;并且是跨平台的。 本教程参考自 Ktor 文档 …

【Linux多线程】线程的终止、等待和分离

文章目录 线程终止正常退出return 退出pthread_exit函数终止线程 pthread_cancel强制终止线程进程终止 线程等待为什么需要等待线程&#xff1f;pthread_join函数 分离线程pthread_detach函数 线程终止 下面给出终止线程的三种方式&#xff1a; 正常退出&#xff1a; 线程执行…

【学习心得】算法刷题心得分享

一、为什么要刷题&#xff1f; 提升编程能力&#xff0c;强化对数据结构的理解&#xff0c;熟练掌握常用的算法等为竞赛、考试做准备找实习、找工作需要&#xff08;上机考试面试手撕代码&#xff09;提升自信心&#xff0c;放松一下 二、刷题前应该有哪些知识储备&#xff1f;…