比特数据结构与算法(第四章_上)树和二叉树和堆的概念及结构

news2025/1/18 20:15:21

1.树概念及结构

1.1树的概念

树是一种非线性的数据结构,它是由 n(n >= 0)个有限节点组成的一个具有层次关系的集合。

那么为什么叫 "树" 呢? (节点也可以称结点,建议称结点,和结构体对上)

我们之所以把它成为 "树",是因为它很像我们现实生活中的树。只是它是倒过来的,根朝上叶子朝下。

① 树有一个特殊的节点,成为根节点,根节点不存在前驱节点。

② 除根节点外,其余节点被分成 M(M>0) 个互不相交的集合 T1、T2、……、Tm,

其中每一个集合 Ti(1 <= i <= m) 又是一颗结构于树类似的字数。

每颗子树的节点有且只有一个前驱,可以有0个或多个后继。

③ 因此,树是递归定义的。因为任何树都会被分成根和子树。

1.2树的相关概念

节点的度一个节点含有的子树的个数称为该节点的度; 如上图:A的为6

叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点

非终端节点或分支节点度不为0的节点; 如上图:D、E、F、G...等节点为分支节点

双亲节点或父节点若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B

的父节点

孩子节点或子节点一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节

兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点

树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6

节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

( 有些书上规定根节点的层数为0,这样空树就是-1了,所以若没有特殊说明默认规定根节点的层数为 1)

树的高度或深度:树中节点的最大层次; 如上图:树的高度为4

节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先

子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙

森林:由m(m>0)棵互不相交的多颗树的集合称为森林;(数据结构中的学习并查集本质就是

一个森林)

注意:树型结构中,子树之间不能有交集,否则就不是树形结构。

1.3树的表示

以前学单链表时只有一个指针,双链表两个指针,但是树有多少个指针是不确定的,

因为树没有规定一个节点最多有多少个孩子。那我们该如何定义结构呢?

法一:假设说明了树的度为N,才能勉强用

struct TreeNode 
{
    int data;
    struct TreeNode* sub[N]; // 指针数组
};

问题点:

① 可能会存在不少的空间浪费。

② 万一没有限定树的度为多少呢?

法二:vector(C++中这里可以用 vector,但是C里没有)

// 假设我们定义了一个顺序表
typedef int STLDataType;  //顺序表的数据类型
typedef struct TreeNode* SLDataType; // 顺序表中存节点的指针
struct TreeNode //SeqList
{
    STLDataType data;
    SeqList s;  // s为SLDataType* array;
};

即使你没有告诉我度是多少,我有多少个孩子我就存多少个孩子,所以这里不需要关心度的问题。

但是这里 s 的结构相对复杂,s 里面有一个类型为SLDataType* 的数组,

这个数组已经是二级指针了,SLDataType 展开后又是一个 struct TreeNode* 。

法三:双亲表示法

struct TreeNode 
{
    int parenti;
    int data;
};

[ A -1] [ B0 ] [ C0 ] [ D0 ] ...... [ H 3 ]

每一个元素中存的是结构体 struct TreeNode arr[10]

每个元素内只存自己的值和父亲的下标

(A没有父亲是-1,B的父亲下标是0…… H的父亲是D下标为3),可以通过一个值找到自己父亲。

上列的方式各有优缺点,那么有没有最优的方法?

当然有,它就是左孩子右兄弟表示法

typedef int DataType;
struct Node 
{
    struct Node* _leftChind1;   // 永远指向第一个孩子
    struct Node* _rightBrother;  // 指向孩子右边的兄弟
    DataType _data;
};

解读:无论你有多少个孩子,它都只存两个指针。一个指针永远指向第一个孩子,

另一个指针指向孩子右边的兄弟(亲兄弟)。这个树的度无论为多少,也不需要用顺序表存,

但是你任何一个节点有多少个孩子都能给你表示出来,通过第一个孩子把所有孩子都找出来。

不复杂也没有浪费,只用两个指针就把链接关系都表示出来了,这就是(古人)的智慧。

1.4树在实际中的运用

文件系统的目录树结构、网络拓扑,最短路径问题,搜索引擎、思维导图等

2.二叉树概念及结构

1.1二叉树的概念

定义:二叉树既然叫二叉树,顾名思义即度最大为2的树称为二叉树。

它的度可以为 1 也可以为 0,但是度最大为 2 。

一颗二叉树是节点的一个有限集合,该集合:

① 由一个根节点加上两颗被称为左子树和右子树的二叉树组成

② 或者为空

观察上图我们可以得出如下结论:

① 二叉树不存在度大于 2 的节点,换言之二叉树最多也只能有两个孩子。

② 二叉树的子树有左右之分,分别为左孩子和右孩子。次序不可颠倒,因此二叉树是有序树。

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

1.2 满二叉树

定义:一个二叉树,如果每一层的节点数都达到了最大值(均为2),则这个二叉树就可以被称作为 "满二叉树" 。

换言之,如果一个二叉树的层数为h ,且节点总数是 2^h-1,则他就是一个满二叉树。

层数为N的计算公式:

十亿个节点,满二叉树是多少层?

≈ 10亿多

1.3完全二叉树

定义:对于深度为h的,有 n个结点的二叉树,当且仅当其每一个结点都与深度为h的满二叉树中编号从 1 至 n的结点一一对应时称之为完全二叉树。

前h-1层是满的,最后一层不满,但是最后一层从左到右是连续的。

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。

所以,满二叉树是一种特殊的完全二叉树(每一层节点均为2)。

常识:

① 完全二叉树中,度为 1 的最多只有 1 个。

② 高度为 的完全二叉树节点范围是

1.4二叉树的性质

四点规则:

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

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

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

④ 若规定根节点的层数为1,具有N个结点的满二叉树的深度h=LogN+1(log以2为底)。

二叉树性质相关选择题:

1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )

A. 不存在这样的二叉树

B. 200

C. 198

D. 199

2.在具有 2n 个结点的完全二叉树中,叶子结点个数为( )

A. n

B. n+1

C. n-1

D. n/2

3.一棵完全二叉树的节点数位为531个,那么这棵树的高度为( )

A. 11

B. 10

C. 8

D. 12

4. 一个具有767个节点的完全二叉树,其叶子节点个数为()

A. 383

B. 384

C. 385

D. 386

答案解析:

1. n0=n2+1

2.假设叶子节点有X个 则度为0的节点有x-1个,完全二叉树中度为1的节点为0个或1个

所以X+(X-1)+0或1=2n,所以叶子结点x个数为n

3.具有N个结点的满二叉树的深度h=LogN+1(log以2为底)。

4.同2 .X+(X-1)+0或1=767 x=384

1.B

2.A

3.B

4.A

1.5二叉树的顺序存储:

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树

会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲

解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

完全二叉树的顺序存储中

若父亲下标是i,则左孩子下标是2*i+1 右孩子下标是2*i+2

若孩子下标是i,则父亲下标是(i-1)/2

像上面左图中C下标为2,左孩子F下标就为2*2+1=3,右孩子G下标为2*2+2=6

D下标为3,E下标为4 则父亲B下标为(3-1)/2=1

1.6二叉树的链式存储:

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的

方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩

子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都

是二叉链,后面课程学到高阶数据结构如红黑树等会用到三叉链。

// 二叉链
struct BinaryTreeNode
{
    struct BinTreeNode* pLeft;   // 指向当前节点左孩子
    struct BinTreeNode* pRight; // 指向当前节点右孩子
    BTDataType _data; // 当前节点值域
}
// 三叉链
struct BinaryTreeNode
{
    struct BinTreeNode* pParent; // 指向当前节点的双亲
    struct BinTreeNode* pLeft;   // 指向当前节点左孩子
    struct BinTreeNode* pRight; // 指向当前节点右孩子
    BTDataType _data; // 当前节点值域
}

3.堆的概念及结构

【百度百科】堆(Heap)是计算机科学中一类特殊的数据结构的统称。
堆通常是一个可以被看做 一棵完全二叉树的数组对象

完全二叉树的性质就是堆的性质,堆是完全二叉树的顺序结构存储。

① 堆总是一棵完全二叉树。

② 堆中的某个节点的值总是不大于或不小于其父节点的值。

堆的物理结构其实是数组,逻辑结构则是二叉树。

堆的调整算法有多种,其中典型的是:大堆 和 小堆。

3.1小堆:

任意一个节点的两个子节点都比自己的值大或相等,也就是根最小,整个二叉树从上到下递增。

父亲位,比孩子位,要小

3.2大堆:

任意一个节点的两个子节点都比自己的值小或相等,也就是根最大,整个二叉树从上到下递减。

父亲位,比孩子位,要大

常考选择题:

解析:

题目只说明是堆,大堆小堆都可以。

一个个分析后发现除了A都不是

A差不多是这样:

100

60 70

50 32 65

3.3堆的作用

① 堆排序

② 解决TopK问题,在N个数中找出最大的前K个或找出最小的K个......

本篇完。

下一篇我们用代码实现一个大堆。

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

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

相关文章

REDIS中的缓存穿透,缓存击穿,缓存雪崩原因以及解决方案

需求引入一般在项目的开发中,都是使用关系型数据库来进行数据的存储&#xff0c;通常不会存在什么高并发的情况&#xff0c;可是一旦涉及大数据量的需求&#xff0c;比如商品抢购&#xff0c;网页活动导致的主页访问量瞬间增大&#xff0c;单一使用关系型数据库来保存数据的系统…

多孔弹性材料中传播的膨胀波方法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

海量并发低延时 RTC-CDN 系统架构设计(下)

上半部分内容&#xff1a;海量并发低延时 RTC-CDN 系统架构设计&#xff08;上&#xff09;低延时 RTC-CDN 系统的架构传统 CDN 直播发展多年&#xff0c;为了优化延时&#xff0c;业界基本上朝两大优化方向&#xff1a;优化传输层协议和在传输层协议的基础上优化应用层协议。R…

Hadoop环境搭建(1)

一、在已安装的虚拟机上面进行修改&#xff08;以CentOS 7为例&#xff09;①修改主机名查看自己主机名&#xff0c;命令hostname第一种修改主机名方法&#xff0c;命令vi /etc/hostname第二种修改主机名方法&#xff0c;命令hostnamectl set -hostname 自定义主机名可以更改为…

简单介绍如何使用robotium进行自动化测试

创建一个简单的工程作为被测程序&#xff0c;运行后显示如下界面&#xff1a; 2.创建一个Test Project 1). 打开eclipse&#xff0c;选择File->New->Project…->Android Test Project&#xff0c;点击Next。 2). 在Test Project Name中输入测试工程的名称&#xff…

华为HCIP-Datacom认证题库(H12-821)

第一套&#xff08;100题&#xff09; 1. &#xff08;单选题&#xff09;下面关于0SPF的特殊区域&#xff0c;描述错误的是: A.Totally Stub Area允许ABR发布缺省的三类LSA,不接受五类LSA和细化三类LSA B.NSSA Area和Stub区域的不同在于该区域允许自治系统外部路由的引入&…

「实践总结」订单超时自动取消

在进行开发的过程中&#xff0c;在开发的时候&#xff0c;有遇到相关的延时支付相关的问题&#xff0c;在解决延时支付的相关的问题的时候&#xff0c;会有很多种的解决办法&#xff0c;现在就讲对应的解决办法先进行相关的总结操作&#xff1b;「引言」在开发中&#xff0c;往…

mysql索引失效的几种情况

失效的几种情况 1、select * from xxx 2、索引列上有计算 3、索引列上有函数 4、like左边包含‘%’ 5、使用or关键字 6、not in和not exists 7、order by 8、不满足最左匹配原则 给code、age和name这3个字段建好联合索引&#xff1a;idx_code_age_name。 该索引字段的顺…

ChatGPT告诉你:项目管理能干到60岁吗?

早上好&#xff0c;我是老原。这段时间最火的莫过于ChatGPT&#xff0c;从文章创作到论文写作&#xff0c;甚至编程序&#xff0c;简直厉害的不要不要的。本以为过几天热度就自然消退了&#xff0c;结果是愈演愈烈&#xff0c;热度未减……大家也从一开始得玩乐心态&#xff0c…

注意,这本2区SCI期刊最快18天录用,还差一步录用只因犯了这个错

发表案例分享&#xff1a; 2区医学综合类SCI&#xff0c;仅18天录用&#xff0c;录用后28天见刊 2023.02.10 | 见刊 2023.01.13 | Accepted 2023.01.11 | 提交返修稿 2022.12.26 | 提交论文至期刊部系统 录用截图来源&#xff1a;期刊部投稿系统 见刊截图来源&#xff1a…

npm link

正文npm link的用法假如我们想自己开发一个依赖包&#xff0c;以便在多个项目中使用。一种可行的方法&#xff0c;也是npm给我们提供的标准做法&#xff0c;那就是我们独立开发好这个 "依赖包"&#xff0c;然后将它直接发布到 npm镜像站 上去&#xff0c;等以后想在其…

熟读阿里总结的 Java10w 字总结,15 天拿下 5 个大厂 offer(阿里,美团,字节...)

Java 面试都会有很多程序员找工作、跳槽等一系列的安排。说实话&#xff0c;面试中 7 分靠能力&#xff0c;3 分靠技能&#xff1b;在刚开始的时候介绍项目都是技能中的重中之重&#xff0c;它也是可以决定一次面试的成败的&#xff0c;那么在面试的时候你会如何介绍自己、熟练…

Sms多平台短信服务商系统~完成阿里云短信服务发送可自行配置

1.项目中引入Maven 阿里云地址 不同编程语言都有对应的SDK,你们下载自己需要的即可。 pom.xml中添加maven坐标 <!--阿里云短信服务--><dependency><groupId>com.aliyun</groupId><artifactId>alibabacloud-dysmsapi20170525</artifactId>…

八、CSS新特性二

文章目录一、CSS3多背景和圆角二、怪异盒子模型三、多列属性四、H5多列布局瀑布流五、CSS3线性渐变5.1 线性渐变5.2 径向渐变六、CSS3过渡动画七、CSS3 2D八、CSS3动画一、CSS3多背景和圆角 css3多背景&#xff0c;表示CSS3中可以添加多个背景。 CSS3圆角 border-radius: 0px;…

日本机载激光雷达测深进展(二)机载激光雷达测深经验

日本海岸警卫队海洋情报部&#xff08;JHOD&#xff09;拥有14年的机载激光雷达测深(ALB)经验。由于ALB调查高效率和高分辨率&#xff0c;JHOD已将ALB应用于各种用途&#xff0c;如制图、海啸受灾港口的恢复重建、安全监测和火山活动研究。本文简要描述了JHOD激光雷达测深系统的…

基于Hibernate对数据库表的单表查询

基于Hibernate对数据库表的单表查询 1.依赖 1.1jar包 1.2配置文件。persistence.xml <?xml version"1.0" encoding"UTF-8"?> <persistence version"2.1"xmlns"http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi"…

docker 部署centos7.9并打包成docker

下载centos基础镜像 docker pull centos:centos7 运行镜像 docker run -itd --name centos-test -p 60001:22 --privileged centos:centos7 /usr/sbin/init 进入容器 docker exec -it ebec90068696 /bin/bash 配置容器信息 安装ssh服务和网络必须软件 yum install net-to…

Linux基础命令-pstree树状显示进程信息

Linux基础命令-uname显示系统内核信息 Linux基础命令-lsof查看进程打开的文件 Linux基础命令-uptime查看系统负载 文章目录 前言 一 命令介绍 二 语法及参数 2.1 使用man查看命令语法 2.2 常用参数 三 参考实例 3.1 以树状图的形式显示所有进程 3.2 以树状图显示进程号…

【计算机网络 -- 期末复习】

例题讲解 IP地址&#xff08;必考知识点&#xff09; 子网掩码 子网划分 第一栗&#xff1a; 子网划分题目的答案一般不唯一&#xff0c;我们主要采用下方的写法&#xff1a; 第二栗&#xff1a; 路由跳转 数据传输 CSMA/CD数据传输 2、比特率与波特率转换 四相位表示&am…

一文高端Android性能优化-总结篇

以下从几个方面来总结一下Android的性能优化&#xff1a;1&#xff1a;界面卡顿优化2&#xff1a;内存优化3&#xff1a;App启动优化界面卡顿优化Android的界面为每秒60帧&#xff0c;即必须在16ms内完成1帧的绘制&#xff0c;如果某个方法耗时过程&#xff0c;导致16ms内无法完…