当前位置:   article > 正文

[入门必看]数据结构5.2:二叉树的概念_数据结构二叉树的概念

数据结构二叉树的概念


第五章 树与二叉树

小题考频:30
大题考频:8


5.2 二叉树的概念

难度:☆☆☆

知识总览

5.2.1_1 二叉树的定义和基本术语

在这里插入图片描述

5.2.1_2 二叉树的性质

5.2.2 二叉树的存储结构

在这里插入图片描述


5.2.1_1 二叉树的定义和基本术语

在这里插入图片描述

二叉树的基本概念

二叉树是 n ( n ≥ 0 ) n(n≥0) n(n0)个结点的有限集合:
①或者为空二叉树,即n = 0。
②或者由一个根结点和两个互不相交的被称为根的左子树右子树组成。左子树和右子树又分别是一棵二叉树。

二叉树也是递归定义的数据结构
在这里插入图片描述

特点:
①每个结点至多只有两棵子树
②左右子树不能颠倒(二叉树是有序树

注意区别:度为2的有序树
度为2的有序树是指,在这个树里面至少会有一个结点,其有两个子树。


二叉树的五种状态

在这里插入图片描述


几个特殊的二叉树

满二叉树

在这里插入图片描述
特点:
①只有最后一层有叶子结点
不存在度为1的结点
按层序从1开始编号,结点i的左孩子为2i右孩子为2i+1;结点i的父节点为[i/2] (如果有的话)【规律】

除了最下面一层叶子结点之外,所有的分支结点都长满了两个分支。
对于高度为h的满二叉树,第一层 2 0 2^0 20个,第二层 2 1 2^1 21个,第三层 2 2 2^2 22个……第h层有 2 h − 1 2^{h-1} 2h1个,对其求和可以算出高度为h的满二叉树有多少个结点。
 
对于有h层的满二叉树,每一层的节点数是上一层节点数的2倍。因此,第i层的节点数为2^(i-1)。将所有层的节点数相加即可得到该满二叉树的总节点数。
∑ i = 0 h − 1 2 i = 2 h − 1 \sum_{i=0}^{h-1}2^{i} = 2^{h} - 1 i=0h12i=2h1
因此,有h层的满二叉树共有 2 h − 1 2^h-1 2h1个节点。

完全二叉树

完全二叉树:如果一棵树里的结点同样按照一层一层的方式编号,这些编号能够和满二叉树一一对应,那么这棵树就是完全二叉树:

可以这么理解,满二叉树每一层的结点都已经满了,不可能再有更多的结点。那么完全二叉树就是在满二叉树的基础上,将其某一些编号更大的结点给去掉。

在这里插入图片描述
特点:
特点:
①只有最后两层可能有叶子结点
最多只有一个度为1的结点
③按层序从1开始编号,结点i的左孩子为2i右孩子为2i+1;结点i的父节点为[i/2] (如果有的话)【规律同上】
④i ≤ [n/2] 为分支结点,i > [n/2] 为叶子结点【可取整】

如果去掉了中间的某个结点,那么编号就无法与满二叉树对应。
只有左边结果之后,才能继续往右边结。
完全二叉树中,如果某结点只有一个孩子,那么一定是左孩子。
在这里插入图片描述

二叉排序树

二叉排序树:一棵二叉树或者是空二叉树,或者是具有如下性质的二叉树:
左子树上所有结点的关键字小于根结点的关键字;
右子树上所有结点的关键字大于根结点的关键字。
左子树和右子树又各是一棵二叉排序树。

在这里插入图片描述

左子树都小于根节点;
右子树都大于根节点

在这里插入图片描述

单独看左子树和右子树,其又是一颗二叉排序树。

基于这种特性,想要在二叉排序树上搜索某一个关键字就会变得很容易。

Eg1.如果想要找到60结点
60大于根节点的关键字19,往右子树找;
右子树根节点是50,小于60,继续往右子树找;
右子树根节点为66,大于60,往左子树找;
找到了关键字为60的结点,至此就完成了一个关键字的搜索。

Eg2.插入新结点68
68大于19,往右;
68大于50,往右;
68大于66,往右;
68小于70,同时已经到叶子结点,让结点68成为结点70的左孩子。
这样就保证了在插入一个新元素之后,这个树依然是二叉排序树。

二叉排序树可用于元素的排序、搜索

平衡二叉树:

平衡二叉树:树上任一结点的左子树和右子树的深度(高度)之差不超过1。

胖胖的、丰满的树

在这里插入图片描述

50的左子树的深度(高度)为2,右子树的深度(高度)为3,满足平衡二叉树的条件。
66的左子树的深度(高度)为1,右子树的深度(高度)为2,满足平衡二叉树的条件。
所有结点都满足。

再看一个例子:
在这里插入图片描述

根节点的左子树深度(高度)为1而右子树深度(高度)为6,其深度(高度)之差已经大于1,不是平衡二叉树。

尽可能追求左右子树的平衡,就可以得到更好的更高效的二叉排序树

给出的这两个例子其实都是二叉排序树,而且里面存的数据元素都是一样的。
如果要搜索关键字为70的结点,在平衡二叉树上往下走2步就可以找到;
在不平衡二叉树上要走很多很多步才能找到。
平衡二叉树能有更高的搜索效率
长得越胖越好,高度尽可能低,从根节点开始往下搜索时,因为高度低,所以搜索的次数就会减少。


5.2.1_2 二叉树的性质

二叉树的常考性质

常见考点1: n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

常见考点1:设非空二叉树中度为0、1和2的结点个数分别为 n 0 n_0 n0 n 1 n_1 n1 n 2 n_2 n2 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1(叶子结点比二分支结点多一个)

度为0的点(叶子结点)比度为2的点要多一个。

假设树中结点总数为n,因为二叉树里只可能有度为0,度为1和度为2这样三种结点,所以三种结点的数量加起来刚好是n
n = n 0 + n 1 + n 2 n = n_0 + n_1 + n_2 n=n0+n1+n2

树的结点个数等于总度数+1
因为对任何一种树来说,除了根节点之外,每一个结点的头上都会连一个分支,总度数就是这些分支的总数量,只有根节点头上是没有分支的,所以得出这样一个结论。
对于二叉树来说,度为1的结点有 n 1 n_1 n1个,度为2的结点有 n 2 n_2 n2个——其每个结点贡献2个度, n 1 + 2 n 2 n_1+2n_2 n1+2n2得到的就是总度数,总度数+1刚好是树的结点个数。
n = n 1 + 2 n 2 + 1 n=n_1+2n_2+1 n=n1+2n2+1

此处用②式-①式就可以得到这个结论:
n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1
 
十分重要

在这里插入图片描述


常见考点2:二叉树和m叉树第i层至多有多少结点

二叉树第i层至多有 2 i − 1 2^{i-1} 2i1个结点(i≥1)
m叉树第i层至多有 m i − 1 m^{i-1} mi1个结点(i≥1)


常见考点3:高度为h的二叉树和m叉树至多有多少结点

高度为h的二叉树至多有2ℎ − 1个结点(满二叉树)
高度为h的m叉树至多有 m h − 1 m − 1 \frac{m^h-1}{m-1} m1mh1个结点
(等比数列求和)


完全二叉树的常考性质

常见考点1:具有n个(n > 0)结点的完全二叉树的高度h为 ⌈ log ⁡ 2 ( n + 1 ) ⌉ \lceil \log _2\left( n+1 \right) \rceil log2(n+1) ⌈ log ⁡ 2 n ⌉ + 1 \lceil \log _2n \rceil +1 log2n+1

具有n个(n > 0)结点的完全二叉树的高度h为 ⌈ log ⁡ 2 ( n + 1 ) ⌉ \lceil \log _2\left( n+1 \right) \rceil log2(n+1) ⌈ log ⁡ 2 n ⌉ + 1 \lceil \log _2n \rceil +1 log2n+1

在这里插入图片描述

n的上下限,取对数

高为h的完全二叉树至少 2 h − 1 − 1 2^{h-1} − 1 2h11 个结点,至多 2 h − 1 2^ℎ − 1 2h1个结点

高为h的完全二叉树至少可以比高为h-1的满二叉树多1个结点

在这里插入图片描述

可以得到:第i个结点所在层次为 ⌈ log ⁡ 2 ( i + 1 ) ⌉ \lceil \log _2\left( i+1 \right) \rceil log2(i+1) ⌈ log ⁡ 2 i ⌉ + 1 \lceil \log _2i \rceil +1 log2i+1


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

在这里插入图片描述

完全二叉树只可能有一个度为一的结点
n 0 n_0 n0为叶子结点, n 2 n_2 n2为两分支结点,所以 n 0 + n 2 n_0+n_2 n0+n2 = 2 n 2 + 1 2n_2+1 2n2+1一定为奇数。

可以得到:

如果一个二叉树有偶数个结点的话,这就意味着 n 0 + n 1 + n 2 n_0+n_1+n_2 n0+n1+n2是一个偶数 2 k 2k 2k,由于 n 0 + n 2 n_0+n_2 n0+n2一定是一个奇数,那么 n 1 n_1 n1的值就是1,得到 n 0 = k n_0 = k n0=k n 2 = k − 1 n_2=k-1 n2=k1

如果一个二叉树有奇数个结点的话,这就意味着 n 0 + n 1 + n 2 n_0+n_1+n_2 n0+n1+n2是一个奇数 2 k − 1 2k-1 2k1,由于 n 0 + n 2 n_0+n_2 n0+n2一定是一个奇数,那么 n 1 n_1 n1的值就是0,得到 n 0 = k n_0 = k n0=k n 2 = k − 1 n_2=k-1 n2=k1


5.2.2 二叉树的存储结构

二叉树的顺序存储

在这里插入图片描述

一个 TreeNode就对应树中一个结点
每一个结点里包含一个ElemType,即实际要存的数据元素。
通过bool型变量来判断是否为空结点。

在这里插入图片描述

初始化数组时,需要把所有元素的isEmpty都设置为true,表示所有数据都是空的,没有存数据。

让t[0]位置空缺,因为完全二叉树的结点编号是从1开始的,从t[1]开始存储,那么数组的下标就刚好反映出完全二叉树里的结点编号。

由于数组是静态数组,长度是有限的,那么完全二叉树可以包含的结点数量也是有限的。

在这里插入图片描述

如果不是完全二叉树,也按照层序将各结点顺序存储:
在这里插入图片描述
在这里插入图片描述

但是我们,把二叉树的结点编号与完全二叉树对应起来,那么也可以反映出逻辑关系。

在这里插入图片描述

但无法判断结点的左右孩子,只能通过isEmpty来判断。
如果isEmpty为true,则说明该位置为空结点。

在这里插入图片描述

使用顺序存储来存储二叉树,里面会有大量空间是闲置的,这样会浪费大量空间。
最坏情况:所有的结点都只有右分支;
那么对于这个高度为h的二叉树,也至少需要 2 h − 1 2^h-1 2h1个存储单元。即高度为h的满二叉树的存储空间。

结论:二叉树的顺序存储结构,只适合存储完全二叉树。


二叉树的链式存储

二叉链表:
在这里插入图片描述

每一个结点都有一个data域用来存放实际的数据元素;
然后还有两个指针,分别指向其左孩子和右孩子;
如果一个结点没有孩子,就把对应的指针设为NULL
由于每个结点都有两个指针域,那么n个结点就有2n个指针域;
除了根节点,其他n-1个结点都连有一个指针,那么其他 n + 1 n+1 n+1个指针指向空,可以利用起来构造线索二叉树

定义结构体:
在这里插入图片描述

定义一颗空树,声明一个指向根节点的指针,初始值为NULL:
在这里插入图片描述
在这里插入图片描述

此时是一个空树

插入根结点,用malloc函数申请一个根结点:
在这里插入图片描述

此时这里在根结点中存入数字1;
并且让根结点的左右指针此时指向NULL

插入新结点,用malloc函数申请一个新结点:
在这里插入图片描述

在该结点中存入2;
把根结点的左孩子指针指向当前结点p
那么利用相同方法可以插入其他结点

在这里插入图片描述

  • 在二叉链表中,找到指定结点p的左/右孩子非常简单

只需要检查该结点的左孩子指针和右孩子指针指向哪里即可。

  • 在二叉链表中,找到指定结点p的父结点需要从根节点开始遍历寻找!

如果数据很多时,通过遍历的方法找某一结点的父结点就会很耗时。

如果在应用场景中,经常需要逆向查找某一结点的父节点
那么可以在该结构体中再定义一个指针,指向其父结点。
在这里插入图片描述

这样的实现方式称为:三叉链表——方便找父结点

下一节中,将介绍如何遍历二叉树的各个结点。


知识回顾与重要考点

5.2.1_1 二叉树的定义和基本术语

在这里插入图片描述

  • 满二叉树
  • 完全二叉树

5.2.1_2 二叉树的性质

在这里插入图片描述


5.2.2 二叉树的存储结构

顺序存储

在这里插入图片描述

  • 顺序存储二叉树,一定要把二叉树的结点编号和完全二叉树一一对应起来。
    ——这样才能通过结点编号来确定各个结点之间的关系。

  • 上文中的探讨,结点都是从1开始。
    ——思考:如果结点从0开始编号,如何找到结点i的左孩子、右孩子和父结点。

链式存储

在这里插入图片描述

  • n个结点的二叉链表共有n+1个空链域
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/610526
推荐阅读
相关标签
  

闽ICP备14008679号