数据结构和算法(八)–二叉树(Binary Tree)
什么是树形结构
- 树形结构是一层次的嵌套结构。 一个树形结构的外层和内层有相似的结构, 所以这种结构多可以递归的表示。
- 树形结构指的是数据元素之间存在着“一对多”的树形关系的数据结构,是一类重要的非线性数据结构。
- 在树形结构中,树根结点没有前驱结点,其余每个结点有且只有一个前驱结点。叶子结点没有后续结点,其余每个结点的后续节点数可以是一个也可以是多个。
树的基本概念
- 数据结构中,使用树形结构表示数据表素之间一对多的关系,树形结构是一种非线型结构。
- 树的定义:
树(Tree)是n(n≥0)个相同数据类型的数据元素的集合.树中的数据元素称为节点(Node).。n=0的树称为空树(Empty Tree);对于n>0的任意非空树T有:- 有且仅有一个特殊的结点称为树的根(Root)结点,根没有前驱结点;
- 若n>1,则除根结点外,其余结点被分成了m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm称为这棵树的子树(Subtree)。
- 由树的定义可知,树的定义是递归的,用树来定义树。因此,树(以及二叉树)的许多算法都使用了递归。
- 树的形式定义为:树(Tree)简记为T,是一个二元组:
T = (D, R) 其中:D是结点的有限集合,R是结点之间关系的有限集合。
树的特点
- 树的根结点没有前驱结点,除根结点之外的所有结点有且只有一个前驱结点。
- 树中的所有结点都可以有零个或多个后继结点。
实际上,第1个特点表示的就是树形结构的“一对多关系”中的“一”,第2特点表示的是“多”。
树的相关术语
- 结点(Node):表示树中的数据元素,由数据项和数据元素之间的关系组成。在图中,共有10个结点。
- 结点的度(Degree of Node):结点所拥有的子树的个数,在图中,结点A的度为3。
- 节点的高度(Height of Node):从当前节点到最远叶子节点的路径上的节点总数。
- 节点的深度(Depth of Node):从根节点到当前节点的路径上的节点总数。
- 树的度(Degree of Tree):树中各结点度的最大值。在图5.1中,树的度为3。
- 叶子结点(Leaf Node):度为0的结点,也叫终端结点。在图5.1中,结点E、F、G、H、I、J都是叶子结点。
- 分支结点(Branch Node):度不为0的结点,也叫非终端结点或内部结点。在图5.1中,结点A、B、C、D是分支结点。
- 孩子(Child):结点子树的根。在图中,结点B、C、D是结点A的孩子。
- 双亲(Parent):结点的上层结点叫该结点的双亲。在图中,结点B、C、D的双亲是结点A。
- 祖先(Ancestor):从根到该结点所经分支上的所有结点。在图中,结点E的祖先是A和B。
- 子孙(Descendant):以某结点为根的子树中的任一结点。在图中,除A之外的所有结点都是A的子孙。
- 兄弟(Brother):同一双亲的孩子。在图5.1中,结点B、C、D互为兄弟。
- 结点的层次/层数(Level of Node):从根结点到树中某结点所经路径上的分支数称为该结点的层次。根结点的层次规定为1,其余结点的层次等于其双亲结点的层次加1。
- 堂兄弟(Sibling):同一层的双亲不同的结点。在图中,G和H互为堂兄弟。
- 树的深度(Depth of Tree):树中结点的最大层次数。在图5.1中,树的深度为3。树的深度等于树的高度
- 无序树(Unordered Tree):树中任意一个结点的各孩子结点之间的次序构成无关紧要的树。通常树指无序树,也被叫做自由树。
- 有序树(Ordered Tree):树中任意一个结点的各孩子结点有严格排列次序的树。二叉树是有序树,因为二叉树中每个孩子结点都确切定义为是该结点的左孩子结点还是右孩子结点。
- 森林(Forest):m(m≥0)棵树的集合。自然界中的树和森林的概念差别很大,但在数据结构中树和森林的概念差别很小。从定义可知,一棵树有根结点和m个子树构成,若把树的根结点删除,则树变成了包含m棵树的森林。当然,根据定义,一棵树也可以称为森林。
树的逻辑表示
二叉树(Binary Tree)
二叉树的特点
-
每个节点的度最大为2(最多拥有两棵子树)
-
左子树和右子树是有顺序的,如果把左右子树顺序颠倒则变了另一个全新的二叉树。
-
即使节点只有一棵子树也要区分左子树和右子树
-
二叉树是一颗有序树
二叉树示例
二叉树的性质
- 非空二叉树的第i层,最多有 2^(i - 1) 个节点 (i >= 1)
- 在高度为h的二叉树上最多有 2^h - 1 个节点(h >= 1)
- 对于任何一颗非空二叉树,如果叶子节点个数为n0,度为2的节点个数为n2,则有:n0 = n2 + 1
- 假设度为1的节点为n1,那么二叉树的节点总数 n = n0 + n1 + n2
- 二叉树的边数 T = n1 + 2 * n2 = n - 1 = n0 + n1 + n2 - 1
真二叉树(Proper Binary Tree)
真二叉树的特点
- 所有节点的度要么为0,要么为2
满二叉树(Full Binary Tree)
满二叉树的特点
- 所有节点的度要么为0,要么为2,而且所有的叶子节点都在最后一层
- 在同样高度的二叉树中,满二叉树的节点数量最多,叶子节点数量最多
- 满二叉树一定是真二叉树,真二叉树不一定是满二叉树
满二叉树的性质
-
假设满二叉树的高度为 h ( h >= 1 ),那么:
-
第 i 层的节点数量:2 ^ ( i - 1 )
-
叶子节点数量:2 ^ ( h - 1 )
-
总结点数n和高度h的关系:
- n = 2 ^ h - 1 = 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + …… + 2 ^ ( h - 1 )
- h = log2( n + 1 )
-
完全二叉树(Complete Binary Tree)
完全二叉树的特点
- 叶子节点只会出现在最后两层,而且最后一层的叶子节点都靠左对齐
- 完全二叉树重根节点至倒数第二层是一棵满二叉树
- 满二叉树是完全二叉树,完全二叉树不一定是满二叉树
完全二叉树的性质
-
度为1的节点只有左子树
-
度为1的节点要么是1个,要么是0个
-
同样节点数量的二叉树,完全二叉树的高度最小
-
假设完全二叉树高度为 h ( h >= 1 ) ,那么:
-
至少有 2 ^ ( h - 1 ) 个节点(2^0 + 2^1 + 2^2 + …… + 2 ^ ( h - 2 ) + 1 )
-
最多有2 ^ h - 1 个节点(2^0 + 2^1 + 2^2 + …… + 2 ^ ( h - 1 ) ,满二叉树)
-
总节点数量n与高度h的关系为:
-
2 ^ ( h - 1) <= n < 2 ^ h
-
h - 1 <= log2( n ) < h
-
h = floor ( log2 ( n ) ) + 1
floor 是向下取整,ceiling 是向上取整
-
-
-
一棵有n ( n > 0 )个节点的完全二叉树,从上到下、从左到右对节点从0开始进行编号,对任意第i个节点有以下性质:
- 如果i = 0 ,那么它是根节点
- 如果i > 0 ,它的父节点的编号为floor ( ( i - 1 ) / 2 )
- 如果2i + 1 <= n - 1,它的左子节点的编号为2i + 1
- 如果2i + 1 > n - 1,它无左子节点
- 如果2i + 2 <= n - 1,它右子节点的编号为2i + 2
完全二叉树的面试题
-
如果一棵完全二叉树有768个节点,求叶子节点的个数
-
假设叶子节点的个数为n0 ,度为1的节点数为n1 ,度为2的节点个数为n2
-
总节点个数 n = n0 + n1 + n2,而且 n0 = n2 + 1
- n = 2 n0 + n1 - 1
-
完全二叉树的n1要么为0,要么为1
- n1 为1时,n = 2 n0,n必然是偶数,所以叶子节点个数 n0 = n / 2,非叶子节点个数 n1 + n2 = n / 2
- n1 为0时,n = 2 n0 - 1,n必然是奇数,所以叶子节点个数 n0 = ( n + 1 ) / 2,非叶子节点个数 n1 + n2 = ( n - 1 ) / 2
-
完全二叉树公式总结:
- 叶子节点个数 n0 = floor( ( n + 1 ) / 2 ) = ceiling( n / 2 )
- 非叶子节点个数 n1 + n2 = floor( n / 2 ) = ceiling( ( n - 1 ) / 2 )