文章目录
二叉树的基本概念
定义
二叉树是一种特殊的树形结构,其特点是每个结点至多只有两颗子树,并且二叉树的子树有左右之分,其次序不可颠倒。
根据树的基本概念可知,二叉树是一棵有序树。
注意:二叉树和度为2的树、度为2的有序树不是同一概念,不要弄混淆。
如果将二叉树的左右子树颠倒,那么将产生一棵新的二叉树(与原来的二叉树不同)。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。
二叉树的性质
-
非空二叉树上的叶结点个数等于度为2的结点个数加1,即 n 0 = n 2 + 1 n_{0}=n_{2}+1 n0=n2+1。
理由:设总结点树为n,度为0的结点数为 n 0 n_{0} n0,度为1的结点数为 n 1 n_{1} n1,度为2的结点数为 n 2 n_{2} n2。则由树的基本概念可知, n = 0 ∗ n 0 + 1 ∗ n 1 + 2 ∗ n 2 + 1 = n 1 + 2 n 2 + 1 n=0*n_{0}+1*n_{1}+2*n_{2}+1=n_{1}+2n_{2}+1 n=0∗n0+1∗n1+2∗n2+1=n1+2n2+1(树的结点总数=结点的度数之和+1),又 n = n 0 + n 1 + n 2 = n 1 + 2 n 2 + 1 n=n_{0}+n_{1}+n_{2}=n_{1}+2n_{2}+1 n=n0+n1+n2=n1+2n2+1,所以有 n 0 = n 2 + 1 n_{0}=n_{2}+1 n0=n2+1。
-
非空二叉树的第k层最多有 2 k − 1 2^{k-1} 2k−1个结点( k ⩾ 1 k\geqslant1 k⩾1)。
理由:由数学归纳法,第 1 层至多有 1 个结点 = 2 0 2^{0} 20个,第 2 层至多有 2 个 = 2 1 2^{1} 21,第 3 层至多有 4 个 = 2 2 2^{2} 22,所以第 k 层至多有 2 k − 1 2^{k-1} 2k−1个
-
高度为h的二叉树至多有 2 h − 1 2^{h}-1 2h−1个结点( h ⩾ 1 h\geqslant1 h⩾1)。
理由: 2 0 + 2 1 + 2 2 + ⋯ + 2 h − 1 = 2 h − 1 2^{0}+2^{1}+2^{2}+\cdots+2^{h-1}=2^{h}-1 20+21+22+⋯+2h−1=2h−1
几种特殊的二叉树
满二叉树
假设一棵二叉树的高度为h,如果它有 2 h − 1 2^{h}-1 2h−1个结点(即二叉树每一层都含有最多的结点),那么这样的二叉树被称为满二叉树。
完全二叉树
假设一棵二叉树的高度为h,有n个结点。按层序编号时,如果它的每个结点都与高度为h的满二叉树中的结点的编号一一对应,那么我们将这样的二叉树称为完全二叉树。
举个🌰
如图,在图b中,如果6号结点没有左孩子(没有12号结点),但有右孩子。那么按层序编号时,这个右孩子的编号为12,与a中的6号结点的右孩子的编号13不对应,因此这颗二叉树不是完全二叉树。
性质
高度为h,结点个数为n的完全二叉树(按层序编号)具有以下性质:
- 若 i ≤ ⌊ n / 2 ⌋ i\leq\lfloor n/2\rfloor i≤⌊n/2⌋,则结点i为分支结点,否则为叶结点,最后一个分支结点的编号为 i ≤ ⌊ n / 2 ⌋ i\leq\lfloor n/2\rfloor i≤⌊n/2⌋。
- 叶结点只可能出现在层次最大的两层上。
- 若有度为1的结点,只可能出现一个(若出现多个则必然违反完全二叉树的定义),度为1的结点只可能是编号为 i ≤ ⌊ n / 2 ⌋ i\leq\lfloor n/2\rfloor i≤⌊n/2⌋的结点。
- 若一个结点为叶结点或其只有左孩子,那么编号大于它的结点必然是叶子结点。
- 若n为奇数,则每个分支结点都有左右孩子(因为减去根结点后,结点个数为偶数)
- 若n为偶数,则编号为n/2的分支结点只有左孩子,没有右孩子,编号小于n/2的结点都有左右孩子。
- 编号为i的结点的双亲结点编号为 ⌊ i / 2 ⌋ \lfloor i/2\rfloor ⌊i/2⌋。
- 若结点 i i i 有左右孩子,则左孩子编号为 2 i 2i 2i,右孩子编号为 2 i + 1 2i+1 2i+1。
- 结点 i i i 所在层次(深度)为 ⌊ log 2 i ⌋ + 1 \lfloor \log_2i \rfloor+1 ⌊log2i⌋+1。
- 具有 n n n 个( n ⩾ 1 n \geqslant 1 n⩾1) 结点的完全二叉树的高度为 ⌈ log 2 ( n + 1 ) ⌉ \lceil \log_2(n+1) \rceil ⌈log2(n+1)⌉或 ⌊ log 2 n ⌋ + 1 \lfloor \log_2 n \rfloor +1 ⌊log2n⌋+1。
二叉排序树
假设有一棵二叉树,如果它满足以下三条性质:
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 左、右子树也分别为二叉排序树;
我们将这样的二叉树称为二叉排序树。
个人定义:
对于一棵二叉树的任意结点来说,如果它满足:
- 若其左子树不为空,则左子树上的所有结点的值均小于它的值。
- 若右子树不空,则右子树上所有结点的值均大于它的值。
我们把这颗二叉树叫做二叉排序树。
注意:二叉排序树一定是指左边小右边大的树,如果左边大右边小,那么这个二叉树不是二叉排序树。
平衡二叉树
假设有一棵二叉树,树中任意一个结点的左子树和右子树的高度之差的绝对值不超过1,我们把这样的二叉树叫做平衡二叉树。
正则二叉树
假设有一棵二叉树,其只有度为0的结点和度为2的结点,我们把这样的二叉树叫做正则二叉树。
二叉树的存储结构
顺序存储结构
二叉树的顺序存储结构是指用一组连续的存储单元按照满二叉树的编号依次自上而下、从左往右存储结点元素。
王道写的按照完全二叉树,但是20年的408统考真题的答案是按照满二叉树的编号,所以这里我也用满二叉树。
链式存储结构
我们一般使用二叉链表来存储二叉树,二叉链表的结点至少包含3个域:数据域,左指针域,右指针域。
cpp
// C++
template <class T>
class TreeNode{
T data;
TreeNode<T> *left, *right;
}
template <class T>
class Tree{
TreeNode<T> *head;
}
在含有n个结点的二叉链表中,存在n+1个空指针域。
理由:二叉链表总共有2*n个指针,n个结点,使用了n-1个指针,所以二叉链表存在n+1个空指针域。
有时候我们也会使用三叉链表来表示二叉树,三叉链表中多余的那个指针指向双亲结点。
cpp
// C++
template <class T>
class TreeNode{
T data;
TreeNode<T> *left, *right, *parent;
}
template <class T>
class Tree{
TreeNode<T> *head;
}