408数据结构-二叉树的概念、性质与存储结构 自学知识点整理

前置知识:树的基本概念与性质


二叉树的定义

二叉树是一种特殊的树形结构,其特点是每个结点至多只有两棵子树(即二叉树中不存在度大于 2 2 2的结点),并且二叉树是有序树,左右子树不能互换。
与树类似,二叉树也以递归形式定义。二叉树是 n n n n ≥ 0 n≥0 n0)个结点的有限集合。当 n = 0 n=0 n=0时,称为空二叉树
n ≠ 0 n≠0 n=0时,二叉树由根结点和两个互不相交的子树组成,左子树和右子树又分别是一棵二叉树。即使树中结点只有一棵子树,因为二叉树有序,也要区分是左子树还是右子树。
二叉树与度为 2 2 2的有序树的区别:

  • 度为 2 2 2的有序树至少有 3 3 3个结点,而二叉树可以为空。
  • 度为 2 2 2的有序树的孩子的左右次序是相对于另一个孩子而言的,若某一结点只有一个孩子结点,则无需区分其左右。而对二叉树上的结点来说,无论其孩子数是否为 2 2 2,均需确定其左右次序。即二叉树的结点次序不是相对于另一个结点而言的,而是确定的。

几种特殊的二叉树

Man! 满二叉树

一棵高度为 h h h,且有 2 h − 1 2^h-1 2h1个结点的二叉树被称为满二叉树。
因为对一个满二叉树来说,第 i i i层有 2 i − 1 2^{i-1} 2i1个结点,一共有 h h h层,则求和结果就是 2 h − 1 2^h-1 2h1
满二叉树的特点:

  1. 只有最后一层有叶子结点。
  2. 不存在度为 1 1 1的结点。
  3. 若层序从 1 1 1开始编号,则对第 i i i个结点,其左孩子必为第 2 i 2i 2i个结点,右孩子必为第 2 i + 1 2i+1 2i+1个结点。如果结点 i i i存在双亲结点,则其双亲必为第 ⌊ i / 2 ⌋ \left\lfloor i/2 \right\rfloor i/2个结点(即对 i / 2 i/2 i/2向下取整)。

(下图来自王道考研408数据结构课程视频 - 二叉树的定义和基本术语)
图片源自王道考研408数据结构课程视频

完全二叉树

一棵高度为 h h h、有 n n n个结点的二叉树,当且仅当其每个结点都与高度为 h h h的满二叉树中编号为 1 − n 1-n 1n的结点一一对应时,称为完全二叉树
完全二叉树的特点:

  1. 只有最后两层(层数最大的两层)可能有叶子结点。
  2. 最多只有一个度为 1 1 1的结点,且该结点只有左孩子而无右孩子。
  3. 层序从 1 1 1开始编号,则对第 i i i个结点,其左孩子必为第 2 i 2i 2i个结点,右孩子必为第 2 i + 1 2i+1 2i+1个结点。如果结点 i i i存在双亲结点,则其双亲必为第 ⌊ i / 2 ⌋ \left\lfloor i/2 \right\rfloor i/2个结点。(同满二叉树)
  4. 对结点 i i i,当 i ≤ ⌊ n / 2 ⌋ i≤ \left\lfloor n/2 \right\rfloor in/2时,该结点为分支结点;当 i > ⌊ n / 2 ⌋ i> \left\lfloor n/2 \right\rfloor in/2时,该结点为叶结点。
  5. n n n为奇数,则每个分支结点都有左孩子和右孩子;若 n n n为偶数,则编号最大的分支结点(编号为 n / 2 n/2 n/2)只有左孩子,没有右孩子,其余分支结点均有左、右孩子。

二叉排序树⭐

左子树上所有结点的关键字均小于根结点的关键字,右子树上所有结点的关键字均大于根结点的关键字,左右子树又各是一棵二叉排序树,这样的二叉树被称为二叉排序树

平衡二叉树⭐

树中任意一个结点的左子树和右子树的高度之差的绝对值不超过 1 1 1,这样的二叉树称为平衡二叉树
如果一棵二叉排序树是平衡的,那么它的搜索效率会高很多。

关于二叉排序树和平衡二叉树,后续章节会有详细介绍,现在暂时了解其概念即可。

正则二叉树

树中每个分支结点都有 2 2 2个孩子,即树中只有度为 0 0 0 2 2 2的结点。


二叉树的性质相关

常见考点1:非空二叉树上的叶结点数等于度为 2 2 2的结点数加 1 1 1,即 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1

假设树中结点总数为 n n n,度为 0 0 0的结点数为 n 0 n_0 n0,度为 1 1 1的结点数为 n 1 n_1 n1,度为 2 2 2的结点数为 n 2 n_2 n2。则有:
n = n 0 + n 1 + n 2 n=n_0+n_1+n_2 n=n0+n1+n2
n = n 1 + 2 n 2 + 1 n=n_1+2n_2+1 n=n1+2n2+1(树的结点数=总度数+1)
联立两式,得 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
这一个考点常在选择题中涉及,需要牢记并灵活应用。

常见考点2:非空二叉树的第 i i i层至多有 2 i − 1 2^{i-1} 2i1个结点( i ≥ 1 i≥1 i1

由树的基本概念与性质可知, m m m叉树的第 i i i层至多有 m i − 1 m^{i-1} mi1个结点( i ≥ 1 i≥1 i1),令 m = 2 m=2 m=2即可。

常见考点3:高度为 h h h的二叉树至多有 2 h − 1 2^h-1 2h1个结点( h ≥ 1 h≥1 h1

由树的基本概念与性质可知,高度为 h h h m m m叉树至多有 m h − 1 m − 1 \frac{m^h-1}{m-1} m1mh1个结点( i ≥ 1 i≥1 i1),令 m = 2 m=2 m=2,得有 2 h − 1 2^h-1 2h1个(满二叉树)。

完全二叉树的性质相关

常见考点1:具有 n n n个结点( n > 0 n>0 n0)的完全二叉树的高度 h h h ⌈ log ⁡ 2 ( n + 1 ) ⌉ \left\lceil {{\log }_{2}}\left( n+1 \right) \right\rceil log2(n+1) ⌊ log ⁡ 2 n ⌋ + 1 \left\lfloor {{\log }_{2}}n \right\rfloor +1 log2n+1

由完全二叉树的已知性质,假设完全二叉树的高度为 h h h,则有

2 h − 1 − 1 < n ≤ 2 h − 1 {{2}^{h-1}}-1<n\le {{2}^{h}}-1 2h11<n2h1 2 h − 1 ≤ n < 2 h {{2}^{h-1}}\le n<{{2}^{h}} 2h1n<2h

取对数后可解得

h − 1 < log ⁡ 2 ( n + 1 ) ≤ h h-1<{{\log }_{2}}\left( n+1 \right)\le h h1<log2(n+1)h h − 1 ≤ log ⁡ 2 n < h h-1\le {{\log }_{2}}n<h h1log2n<h

h = ⌈ log ⁡ 2 ( n + 1 ) ⌉ h=\left\lceil {{\log }_{2}}\left( n+1 \right) \right\rceil h=log2(n+1) h = ⌊ log ⁡ 2 n ⌋ + 1 h=\left\lfloor {{\log }_{2}}n \right\rfloor +1 h=log2n+1

由此可知,第 i i i个结点所在层次为 ⌈ log ⁡ 2 ( i + 1 ) ⌉ \left\lceil {{\log }_{2}}\left( i+1 \right) \right\rceil log2(i+1) ⌊ log ⁡ 2 i ⌋ + 1 \left\lfloor {{\log }_{2}}i \right\rfloor +1 log2i+1

常见考点2:对于完全二叉树,可以由结点数 n n n推出度为 0 0 0 1 1 1 2 2 2的结点个数 n 0 n_0 n0 n 1 n_1 n1 n 2 n_2 n2

由之前的结论可知,完全二叉树最多只有一个度为 n n n的结点,即 n 1 = 0 n_1=0 n1=0 1 1 1
n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1,则 n 0 + n 2 = 2 n 2 + 1 n_0+n_2=2n_2+1 n0+n2=2n2+1必为奇数。
若完全二叉树有 2 k 2k 2k(偶数)个结点,则必有 n 1 = 1 n_1=1 n1=1 n 0 = k n_0=k n0=k n 2 = k − 1 n_2=k-1 n2=k1
若完全二叉树有 2 k − 1 2k-1 2k1(奇数)个结点,则必有 n 1 = 0 n_1=0 n1=0 n 0 = k n_0=k n0=k n 2 = k − 1 n_2=k-1 n2=k1


二叉树的存储结构

1.顺序存储结构

二叉树的顺序存储是指用一组连续的存储单元依次自上而下、自左而右存储完全二叉树上的结点元素,即将完全二叉树上编号为 i i i的结点元素存储在一维数组下标为 i − 1 i-1 i1的分量中。
依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映结点之间的逻辑关系。这样既能最大可能地节省空间,又能利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。

#define MaxSize 100
typedef struct TreeNode {int value;//结点中的数据元素bool isEmpty;//结点是否为空
}TreeNode;
TreeNode t[MaxSize];//静态顺序存储二叉树
int n;//记录结点总数void TreeInit() {//初始化for (int i = 0; i < MaxSize; ++i)t[i].isEmpty = true;//将每个结点状态设为空return;
}

用这种方式存储的完全二叉树,对第 i i i个结点,其左孩子为 2 i 2i 2i,右孩子为 2 i + 1 2i+1 2i+1,父节点为 ⌊ i / 2 ⌋ \left\lfloor i/2 \right\rfloor i/2,所在层次为 ⌈ log ⁡ 2 ( i + 1 ) ⌉ \left\lceil {{\log }_{2}}\left( i+1 \right) \right\rceil log2(i+1) ⌊ log ⁡ 2 i ⌋ + 1 \left\lfloor {{\log }_{2}}i \right\rfloor +1 log2i+1
若该完全二叉树共有 n n n个结点,则对第 i i i个结点,判断其是否有左右孩子,以及是否为分支/叶子结点,可用以下逻辑实现:

bool Have_LeftChild(int i) {//判断结点i是否有左孩子return (2 * i <= n && !t[2 * i].isEmpty) ? true : false;
}bool Have_RightChild(int i) {//判断结点i是否有右孩子return (2 * i + 1 <= n && !t[2 * i + 1].isEmpty) ? true : false;
}bool Is_Leaf(int i) {//判断结点i是否为叶子结点return i > (n / 2) ? true : false;
}

如果不是完全二叉树,依旧按照顺序存储的方式存储二叉树,则数组下标将不再能够表示各结点之间的逻辑关系。为解决这个问题,可以将二叉树中的结点编号与完全二叉树一一对应,从而进行顺序存储。但是这样又会产生新的问题:假如一棵二叉树中除叶结点外的所有结点都只有右孩子,那么,若这棵二叉树深度为 h h h,则它需要使用 2 h − 1 2^h-1 2h1大小的数组对所有结点进行存放,空间利用率非常非常低。因此,除了完全二叉树可以采用顺序存储结构,一般的二叉树通常采用的都是链式存储结构。

2.链式存储结构

由于顺序存储的空间利用率较低,因此二叉树一般都采用链式存储结构,用链表结点来存储二叉树中的每个结点。在二叉树中,结点结构通常包括若干数据域和若干指针域。二叉链表至少包含 3 3 3个域:数据域 d a t a data data,左指针域 l c h i l d lchild lchild,右指针域 r c h i l d rchild rchild。实际运用中,还可以增加数据域或指针域比如增加一个指向父节点的指针,变成三叉链表的存储结构。
二叉树的链式存储结构描述如下:

typedef struct Elemtype {//复合数据域int value;//只有一个int类型
}Elemtype;
typedef struct BiTNode {//二叉链表结点Elemtype data;//数据域struct BiTNode* lchild, * rchild;//左、右孩子指针
//	struct BiTNode* parent;//父节点指针(根据实际需要决定是否添加)
}BiTNode, * BiTree;

由二叉链表的性质, n n n个结点的二叉链表共有 n + 1 n+1 n+1个空指针域,这一部分可用于构造线索二叉树。
(计算方法:度为 2 2 2的结点有 0 0 0个空指针域,度为 1 1 1的结点有 1 1 1个空指针域,度为 0 0 0的结点有 2 2 2个空指针域。由此前的性质可知,当 n 1 = 1 n_1=1 n1=1时, n 0 = n / 2 n_0=n/2 n0=n/2,空指针域数量为 1 + 2 ∗ n / 2 = n + 1 1+2*n/2=n+1 1+2n/2=n+1;当 n 1 = 0 n_1=0 n1=0时, n 0 = ( n + 1 ) / 2 n_0=(n+1)/2 n0=(n+1)/2,空指针域数量为 0 + 2 ∗ ( n + 1 ) / 2 = n + 1 0+2*(n+1)/2=n+1 0+2(n+1)/2=n+1。故无论 n n n的值为奇数还是偶数, n n n个结点的二叉链表的空指针域都为 n + 1 n+1 n+1个)

根结点的初始化操作如下:

BiTree root = NULL;//定义一棵空树
void InitBiTree() {//初始化根结点root = (BiTree)malloc(sizeof(BiTNode));root->data = { 1 };
//	root->parent = NULL;root->lchild = NULL;root->rchild = NULL;return;
}

插入根结点的左孩子:可依照此逻辑完成对二叉树的构建。

void InsertRLChild() {//插入新节点(根结点的左孩子)BiTNode* p = (BiTNode*)malloc(sizeof(BiTNode));p->data = { 2 };p->lchild = NULL;p->rchild = NULL;root->lchild = p;
//	p->parent = root;return;
}

完整代码可以看我的Github:传送门

若要对二叉树进行遍历,只能从根结点开始,依次向下。在之后的章节里还会继续讨论这个问题。
408考研初试中,通常都是考察不带父指针的情况,即考察使用二叉链表存储二叉树。
若从 0 0 0开始对结点进行编号,则对应的操作逻辑都需要进行更改。
以上。

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

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

相关文章

探索和构建 LLaMA 3 架构:深入探讨组件、编码和推理技术(三)KV缓存

探索和构建 LLaMA 3 架构&#xff1a;深入探讨组件、编码和推理技术&#xff08;三&#xff09; KV缓存 在推理的每一步中&#xff0c;只对模型输出的最后一个标记感兴趣&#xff0c;因为已经有了之前的标记。然而&#xff0c;模型需要访问所有先前的标记来决定输出哪个标记&…

07 - 步骤 javaScript代码

简介 JavaScript 代码是通过 JavaScript 脚本步骤来执行 JavaScript 脚本的一种方式。这允许用户在 Kettle 的数据流程中使用 JavaScript 编写自定义的脚本逻辑&#xff0c;用于数据处理、转换、计算等操作。 使用 场景 我需要在数据流加一个字段 createTime 当前时间&…

《有限元分析及应用》《有限元分析基础教程》-曾攀-清华大学|pdf电子书+有限元分析及应用视频教程(全85讲) 曾攀、雷丽萍 ​​​+课件PPT

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

找不到msvcr110.dll的多种解决方法,轻松解决dll问题

在日常使用计算机的时候&#xff0c;突然提示&#xff1a;“由于找不到msvcr110.dll&#xff0c;无法继续执行代码”。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。这个问题可能会给用户带来困扰&#xff0c;但是不用担心&#xff0c;下面…

QT:输入类控件的使用

LineEdit 录入个人信息 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QString>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 初始化输入框ui->lineEdit…

stm32f103zet6_串口实现-DHT11-tim1(定时)

1思路 1打开时钟 1.1使用定时器实现us级的计时 1.2在打开串口 1,3在DHT11驱动中修改引脚 stm32cudeMX 配置 1打开时钟 2打开串口 3打开tim1(定时器) 4生成代码 代码设置 1导入DHT11库(tim.h是定时器的文件系统自动生成的) DHT11.c #include "dht11.h" #inc…

真香!剪映专业版VIP,解锁限制功能!

01 软件介绍 剪映专业版采用更直观更全能易用的创作面板&#xff0c;让专业剪辑变得更简单高效&#xff0c;为更多人提供畅爽的专业剪辑体验&#xff0c;让更多人享受视频创作的乐趣! 剪映专业版引入强大黑罐头素材库&#xff0c;支持搜索海量音频、表情包、贴纸、花字、特效…

TCP协议在物联网中的实战

一、TCP协议介绍 网上对TCP协议介绍众多&#xff0c;本人按照自己的理解简单介绍一下。 TCP&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输控制层通信协议。 1.1 协议机制 1.1.1 三次握手 &…

使用LwIP实现TCP Client通信(基于STM32F407)

目录 概述 1 功能介绍 1.1 代码框架 2.2 搭建系统 2 TCP Client功能实现 2.1 代码实现 2.2 具体代码 3 功能测试 3.1 测试功能描述 3.2 运行代码 测试代码下载地址&#xff1a; stm32-f407-dm9161-LwIP-tcp-client资源-CSDN文库 概述 本文主要介绍使用STM32F407和…

【多变量控制系统 Multivariable Control System】(1)DSM:术语、基本公式和MATLAB仿真【新加坡南洋理工大学】

说明&#xff1a; 题目版权归校方所有&#xff0c;仅供学习和参考使用。 DSM Control DSM Direct Synthesis Method Process Model Closed-Loop Transfer Function 基本公式 &#xff08;1&#xff09;输入、输出关系 &#xff08;2&#xff09;控制器表示 MatLab仿真…

【navicat】oracle library is not loaded 问题复现和解决方案

问题原因&#xff1a;客户端oci版本安装错误&#xff0c;navicat需要64位的oci,但是使用32位的oci。 解决方案&#xff1a;官网下载64位oci进行配置。本次演示的解决多了splplus&#xff0c;其实不必要安装也能运行。 首先判断是否数据库已经打开 尝试使用splplus连接数据库 1…

JavaScript中的Math对象方法、Date对象方法

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f31f;Math对象方法&#x1f344;1 Math静态属性&#x1f344;2 Math…

【c++】继承学习(一):继承机制与基类派生类转换

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们来学习继承部分 目录 1.继承的概念和定义继承的定义继承基类成员的访问方式变化 2.基类和派生类对象赋值转换3.继承中的作用域 1.继承的概念和定义 …

Costas-Barker序列模糊函数仿真

文章目录 前言一、Costas 序列二、Barker 码三、Costas-Barker 序列模糊函数仿真1、MATLAB 核心代码2、仿真结果①、Costas-Barker 模糊函数图②、Costas-Barker 距离模糊函数图③、Costas-Barker 速度模糊函数图 四、资源自取 前言 Costas 码是一种用于载波同步的频率调制序列…

基于Ollama+AnythingLLM轻松打造本地大模型知识库

随着人工智能技术的快速发展&#xff0c;大型语言模型&#xff08;LLM&#xff09;已成为自然语言处理领域的重要工具。然而&#xff0c;这些模型的运行通常需要大量的计算资源和复杂的部署流程。为了解决这个问题&#xff0c;Ollama应运而生&#xff0c;成为了一个高效的本地大…

学浪的缓存怎么导出来

学浪的缓存导出问题困扰着许多用户&#xff0c;备份和管理数据变得至关重要。在数字化时代&#xff0c;保护和利用数据是企业和个人不可或缺的需求。在这篇文章中&#xff0c;我们将深入探讨学浪缓存导出的方法&#xff0c;为您解决疑惑&#xff0c;让您轻松掌握数据的安全与便…

237基于matlab的偏振态仿真

基于matlab的偏振态仿真&#xff0c;不同偏振态下光强计算。本仿真软件可以仿真波片对偏振光的相位调制过程。用户可以通过改变波片的类型&#xff0c;波片长轴与 X 轴的夹角&#xff0c;起偏器透光与 X 轴的夹角&#xff0c;检偏器透光轴与 X 轴的夹角等参数&#xff0c;来观察…

毫米波雷达原理(含代码)(含ARS548 4D毫米波雷达数据demo和可视化视频)

毫米波雷达原理 1. 传统毫米波雷达1.1 雷达工作原理1.2 单目标距离估计1.3 单目标速度估计1.4 单目标角度估计1.5 多目标距离估计1.6 多目标速度估计1.7多目标角度估计1.7 总结 3. FMCW雷达数据处理算法4. 毫米波雷达的目标解析(含python代码)5. ARS548 4D毫米波雷达数据demo(含…

docker学习笔记3:VmWare CentOS7安装与静态ip配置

文章目录 一、安装CentOS71、下载centos镜像2、安装二、设置静态ip三、xshell连接centos本专栏的docker环境是在centos7里安装,因此首先需要会安装centos虚拟机。 本篇博客介绍如何在vm虚拟机里安装centos7。 一、安装CentOS7 1、下载centos镜像 推荐清华源,下载如下版本 …

GPU虚拟化和算力隔离探讨

1. 术语介绍 术语 全称 说明 GPU Graphics Processing Unit 显卡 CUDA Compute Unified Device Architecture 英伟达2006年推出的计算API VT/VT-x/VT-d Intel Virtualization Technology -x表示x86 CPU&#xff0c;-d表示Device SVM AMD Secure Virtual Machine …