当前位置: 首页 > news >正文

数据结构:二叉树概念篇(算法基础)

目录

一.有向树的图论基础

1.有向树的相关基本概念

有向树的基本定义:

有向树的结点的度:

有向树的度:

有向树的根结点,分枝结点,叶结点: 

树的子树:

树结点的层次:

树的高度:

2.一个基本的数学结论

3.有序有向树

二.数据结构中树的顺序存储结构与链式存储结构

1.数据结构的物理结构与逻辑结构

2.物理结构为顺序表(数组)的树形数据结构

3. 物理结构为链表的树形数据结构

三.二叉树

1.二叉树基本概念 

2.两个重要的特殊二叉树

3. 关于二叉树的一些常用数学结论

(1).第一组结论 

(2).第二组结论(数组实现二叉树的算法基础)


一.有向树的图论基础

基本引理:如果图G(结点数大于等于2)中不存在回路,则至少有一个结点的度为1 

本篇所讨论的树都是有向树 

1.有向树的相关基本概念

  • 有向树的基本定义:

设T是由有限个结点构成有向简单连通图,且T的无向底图不存在任何回路,则称T为有向树:

  • 有向树的结点的度:

 结点的入度:现有树结点A,以A为终点的有向边的条数称为结点A的入度:

结点的出度: 现有树结点A,以A为起点的有向边的条数称为结点A的出度:

以结点A为终点的有向边的另一端的结点称为A的父结点(parent)

以结点A为起点的有向边的另一端的结点称为A的孩子结点(child)

  •  有向树的度:

有向树的度 = 该树所有结点的出度中的最大值:

  • 有向树的根结点,分枝结点,叶结点: 

  1. 根结点的入度为0
  2. 叶结点的出度为0
  3. 其余入度和出度均不为0的结点称为树的分枝结点  
  •  树的子树:

将一个有向树T的根结点去掉,该树则会被分成若干个互不连通的子树,如图:

上图中T的子树t1,t2,t3都可以再以相同的方式被划分成更小的子树直到树图被划分为若干树叶.

注意:在仅有一个根结点的树形结构中子树之间没有通路(不然图中会出现回路)

  • 树结点的层次:

从根结点开始算起沿着有向边进行遍历,根结点某一个特定结点所遍历的结点个数称为某特定结点的层次

  1.  层次相同父结点相同的结点互为兄弟结点(比如上图中的E和F)
  2.  层次相同父结点不同的结点互为堂兄弟结点(比如上图中的F和G)
  • 树的高度:

树的所有结点的层次中的最大值称为该树的高度:比如上图中的树的高度为4

2.一个基本的数学结论

  • 关于树的一个基本命题:若树有n个结点,m条有向边,则m=n-1;

该性质可以通过数学归纳法进行证明:

  1. 显然n=1时,则m=0,m=n-1成立;
  2. 假设n=k(k>=1)时命题成立,任意具有k个结点的树都有k-1条边
  3. 设树G有n=k+1个结点时(k>=1)边数为m。 由于G中没有回路,根据基本引理G中必然存在度(出度+入度)为1的结点,设这个结点为u。 从G中删去结点u(相当于同时删去了一条边和一个结点)根据定义G仍是树,(根据n=k时的假设2)G有k个节点,故有k-1条边,从而m=(k-1)+1=k=n-1(将u结点加回来,边数相应地增加1)。(即若n=k时命题成立则n=k+1时命题也成立,那么从n=1开始构建任意结点数量的树也满足m=n-1)

该证明过程充分体现了树在逻辑上是递推构建起来的图:

分析树的构建图解可知:

  • 若构建仅有一个根结点的有向树,则该有向树的每棵子树的根结点有且只有一个父节点可以有0个或多个孩子结点.
  • 同时易知:在仅有一个根结点的树形结构中,一棵树的子树之间不存在通路

3.有序有向树

满树的概念:

  • 设(单个根结点)树T的高度为h(h>1),度为k(k>=1)(树的结点个数大于1)
  • 树T对应的满树的概念:高度为h根结点每一个分枝结点的出度都为k的树
  • 有序有向树的每一个结点都有自己固定的编号

 有序有向树各结点的编号规则:

  1. 设现在有一颗高度为h,度为k的(单个根结点的)树T(h>1,,k>=1)
  2. 先作出树T对应的满树
  3. 树T对应的满树的各结点按照从低层到高层,从左往右的次序进行编号
  4. 根据满树各结点的编号对树T相应位置的结点进行编号

比如:

二.数据结构中树的顺序存储结构与链式存储结构

如果将树的结点看成是一个个内存区块,结点间的有向线段看成是各内存区块之间的关联(这种关联可能是通过指针或者数组下标关系建立起来的),这种在内存中形成的数据结构就是树形数据结构

1.数据结构的物理结构与逻辑结构

  • 数据结构的物理结构指的是该数据结构在内存中的真实分布模型
  • 数据结构的逻辑结构指的是数据结构的抽象分析模型

数据结构的类型主要取决于其逻辑结构,其逻辑结构和物理结构之间是通过逻辑映射来建立联系的

2.物理结构为顺序表(数组)的树形数据结构

  • 现有一颗度数为2的非满树T
  • 我们先将一个树T对应的满树的各个结点按照从低层次到高层次,从左往右的顺序进行编号:
  •  由此我们可以得到树T各个结点的编号:
  • 根据树T各结点的编号我们就可以将这棵树映射到一个数组上去:
  • 通过结点编号与数组下标的绝对映射,我们便可以通过数组来实现树形数据结构(有序有向树) 
  • 顺序表实现的树中,非常经典的例子就是堆(大小根堆)

3. 物理结构为链表的树形数据结构

我们可以定义一个结构体类型:

typedef int DataType;
struct Node
{struct Node* _firstChild1;  // 第一个孩子结点struct Node* _pNextBrother; // 指向其下一个兄弟结点DataType _data;             // 结点中的数据域
};
  • _firstChild1用于指向该结点的第一个孩子结点(编号意义上的第一个(位于左侧))
  • _pNextBrother用于指向与该结点位于相同层次具有相同父结点兄弟结点

现在有一颗树:

我们用链式存储结构来实现它:

通过_firstChild1指针我们可以实现树的深度遍历

通过_pNextBrother指针我们可以实现树的广度遍历

三.二叉树

1.二叉树基本概念 

一棵二叉树是结点的一个有限集合:

  1. 二叉树的度为2,即不存在出度大于2的结点
  2. 二叉树结点的孩子结点有左右之分(左右孩子),次序不能颠倒,二叉树是有序有向树(各结点都有自己对应的固定编号)

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

2.两个重要的特殊二叉树

  • 满二叉树:一个二叉树,如果根结点和每一个分枝结点的出度都为2,则这个二叉树就是满二叉树。从结点总个数角度分析:如果一个二叉树的层数为K,且结点总数是2^k - 1(等比数列求和),则它就是满二叉树.
  • 完全二叉树:完全二叉树是效率很高的数据结构;
    对于高度为K的,有n个结点的二叉树,当且仅当其所有结点编号为1到n连续排列时称之为完全二叉树。(基于完全二叉树的结点编号特点,用数组来实现完全二叉树,内存利用率较高)

完全二叉树有一个特点:

若完全二叉树的高度为k(k>1),则其前k-1层所有结点构成的子结构是一颗满树

  •  用数组实现完全二叉树非完全二叉树的对比:可见完全二叉树的优势所在
  •  数据结构堆就是用顺序表(数组)实现的完全二叉树(堆是堆排序算法的结构基础)

3. 关于二叉树的一些常用数学结论

接下来我们给出两组在后续的算法学习中会用到的关于二叉树的数学结论

(1).第一组结论 

  • 对任何一棵二叉树, 如果出度为0其叶结点个数为N0, 出度为2的分支结点个数为N2(包括根) ,则有 N0= N2+1

证明:

设该二叉树出度为1的分枝结点个数为N1;

该二叉树中的总边数为: 2*N2 + N1;

二叉树中的总结点个数为: N0 + N1 + N2

根据第一章第2小节的基本数学结论有:2*N2 + N1 = N0 + N1 + N2 -1(树的总边数 = 结点数-1)

化简可得:N0 = N2 +1;(即二叉树中,出度为0的树叶永远比出度为2的分枝结点(包括根)多一个)

(2).第二组结论(数组实现二叉树的算法基础)

  • 定理一:对于具有n个结点的完全二叉树,按照第一章第3节所述的编号规则将其各结点进行编号(根结点我们规定编为0号,则完全二叉树的各结点编号为0~n-1),则对于编号为child的结点有如下结论:若child>0,child编号结点的父结点编号parent = (child-1)/2;若child=0 ,该结点无父结点 

定理一证明图解:

  • 定理二:对于具有n个结点的完全二叉树,按照第一章第3节所述的编号规则将其各结点进行编号(根结点我们规定编为0号,则完全二叉树的各结点编号为0~n-1),则对于编号为parent的结点有如下结论:2*parent+1<n,则可得该结点的左孩子结点编号leftchild = 2*parent+1;若2*parent+1>=n,则该结点无左孩子(该结论是定理一的逆定理)
  • 定理三:对于具有n个结点的完全二叉树,按照第一章第3节所述的编号规则将其各结点进行编号(根结点我们规定编为0号,则完全二叉树的各结点编号为0~n-1),则对于编号为parent的结点有如下结论:若2*parent+2<n,则可得该结点的右孩子结点编号rightchild = 2*parent+2;若2*parent+2>=n该结点无右孩子(该结论是定理一的逆定理)

定理二和三的证明分析图解:

有了该组定理我们就可以通过一个父结点的编号找到其左右孩子结点的编号,反过来也可以通过孩子结点的编号找到其父结点的编号(该组定理为数组实现二叉树奠定了算法基础)

  • 该组定理在后续堆的实现中的堆元素插入删除接口元素上下调整算法中会用到

相关文章:

数据结构:二叉树概念篇(算法基础)

目录 一.有向树的图论基础 1.有向树的相关基本概念 有向树的基本定义: 有向树的结点的度&#xff1a; 有向树的度: 有向树的根结点,分枝结点,叶结点: 树的子树: 树结点的层次: 树的高度: 2.一个基本的数学结论 3.有序有向树 二.数据结构中树的顺序存储结构与链式存…...

华为OD机试真题Java实现【字符串变换最小字符串】真题+解题思路+代码(20222

字符串变换最小字符串 给定一个字符串s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。 变换规则:交换字符串中任意两个不同位置的字符。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Java)真题目录汇总 ## 输入输出描述: …...

数字化转型的企业会用低代码平台深化重塑什么形态

随着数字化转型的浪潮不断推进&#xff0c;越来越多的企业开始关注如何更好地利用数字技术提高业务效率和创新能力。而低代码平台作为一种能够快速构建和部署应用程序的新型工具&#xff0c;正越来越受到企业的青睐。那么&#xff0c;数字化转型的企业会用低代码平台深化重塑什…...

【华为OD机试模拟题】用 C++ 实现 - 拼接 URL(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...

六千字让你明白什么是数字孪生?

文章目录1. 背景2. 数字孪生基础2.1 概念2.2 价值3. 技术生态3.1 技术体系3.2 核心技术3.2.1 多领域、多尺度融合建模3.2.2 数据驱动与物理模型融合的状态评估3.2.3 数据采集和传输3.2.4 全生命周期数据管理3.2.5 虚拟现实呈现3.2.6 高性能计算3.3 建设3.3.1 重点3.3.1.1 数字孪…...

判断字符串是否是纯数字不包括符号(含符号显示False)isnumeric()和isdigit()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断字符串是否是纯数字 不包括符号&#xff08;含符号显示False&#xff09; isnumeric()和isdigit() [太阳]选择题 对于代码中当s为‘二十六’时isdigit()和isnumeric()输出的结果是? s …...

计算机408考研先导课---C语言难点2

目录 一、字符型数据与字符串型数据的比较 1、字符型数据特点 2、字符串型数据特点 二、字符数组 1、定义 2、输入输出 ①输入 ②输出 3、字符处理函数 ①put函数 ②gets函数 ③strcat函数 ④strcpy函数 ⑤strcmp函数 ⑥strlen函数 ⑦strlwr函数 ⑧strup…...

682. 棒球比赛

题目&#xff1a;你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录的第 i 项操…...

【《C Primer Plus》读书笔记】第13章:文件输入/输出

【《C Primer Plus》读书笔记】第13章&#xff1a;文件输入/输出13.1 与文件进行通信13.1.1 文件是什么13.1.2 文本模式和二进制模式13.1.3 I/O的级别13.1.4 标准文件13.2 标准I/O13.3 一个简单的文件压缩程序13.4 文件I/O&#xff1a;fprintf()、fscanf()、fgets()和fputs()13…...

Datacom-HCIE考试经验分享

我是誉天Datacom秦同学。作为誉天众多通过Datacom-HCIE考试的学员之一&#xff0c;我感到很荣幸。 首先说说自学的感受吧&#xff1a; 我是从2020年开始接触网络行业的&#xff0c;听单位的前辈说华为的HCIE认证是行业含金量最高的证书&#xff0c;从那时起心里就种下了一个“I…...

第十二章 系统错误消息 - 一般系统错误消息 P - S

文章目录第十二章 系统错误消息 - 一般系统错误消息 P - S第十二章 系统错误消息 - 一般系统错误消息 P - S 错误代码描述<PARAMETER>由用户编写的函数引用或 Do 命令传递给标记行的参数数量超过了为标记行声明的形式参数的数量。<PRIVATE METHOD>已尝试调用一个私…...

【git】Idea中git的使用

配置git 创建git仓库 不同颜色代表的含义 红色——未加入版本控制&#xff1b;绿色——已经加入控制暂未提交&#xff1b;蓝色——加入&#xff0c;已提交&#xff0c;有改动&#xff1b;白色——加入&#xff0c;已提交&#xff0c;无改动&#xff1b;灰色——版本控制已忽略文…...

Centos安装Python、PyCharm

安装Python 1、打开终端(Terminal) 2、输入以下命令更新系统&#xff1a; sudo yum update 3、安装Python&#xff1a; sudo yum install python3 4、安装完成后&#xff0c;可以使用以下命令检查Python版本&#xff1a; python3 --version 安装PyCharm 1、下载PyCharm的安…...

搞百亿补贴,京东不能只“砸钱”

出品 | 何玺 排版 | 叶媛 京东“百亿补贴”真的要来了。 据多家媒体报道&#xff0c;京东“百亿补贴”已于2月23日启动内测。根据此前消息&#xff0c;京东“百亿补贴”频道将于3日晚8点正式上线。 在京东“百亿补贴”频道正式上线之前&#xff0c;我们来聊一聊“刘强东为什…...

automl介绍以及代码实例

使用AutoML来自动构建机器学习模型&#xff0c;可以使用多种不同的Python包&#xff0c;包括AutoGluon、TPOT、Auto-Keras等。AutoGluon可以自动搜索最佳模型&#xff0c;以便满足开发人员的需求&#xff1b;TPOT可以自动调整模型的参数&#xff0c;以获得更好的性能&#xff1…...

kill 与killall

【查询命令所属软件包】 rpm -qf /usr/bin/killall psmisc-22.20-15.el7.x86_64 rpm -qf /usr/bin/kill util-linux-2.23.2-65.el7_9.1.x86_64 【命令参数】 killallkill -e,--exact require exact match for very long names -I,--ignore-case case insensi…...

【加密】开发常见加密类型

相关加密方法具体使用&#xff0c;查阅工具官方&#xff1b; 对称加密&#xff08;单密钥加密&#xff09;&#xff1a;常用于传输数据加密 信息的加密和解密使用相同密钥&#xff1b; 常见对称算法&#xff1a; DES&#xff08;Data Encryption Standard&#xff09;&#x…...

数据结构之基:从根儿上了解数据结构的特性

学好数据结构&#xff0c;就等于成功了一半。 程序是对现实的模拟&#xff0c;现实是由时间和空间组成的&#xff0c;高效的人都是用最少的时间、最少的空间来做最伟大的事&#xff0c;程序亦是如此。我们要选择最合理的算法和最合理的数据结构&#xff0c;来写最好的代码&…...

C++ 枚举详解

C 枚举详解 C 枚举类型详解 枚举类型的定义格式为&#xff1a; enum <类型名> {<枚举常量表>};关键字enum——指明其后的标识符是一个枚举类型的名字枚举常量表——由枚举常量构成。“枚举常量"或称"枚举成员”&#xff0c;是以标识符形式表示的整型量&…...

【vue3】ref , reactive ,toRef ,toRefs 使用和理解

这篇文章是基于理解写的&#xff0c;仅助于理解&#xff0c;如有任何错误之处&#xff0c;感谢指正&#xff01; 文章目录一.ref的使用1. ref的功能主要有两个&#xff1a;2.使用ref注意事项二.reactive的使用三.使用ref 和 reactive 实现双向数据绑定四.toRef 和 toRefs 的使用…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...