树的基础概念与性质
树
定义
- 由
n (n >= 0)个结点组成的有限集合。 n = 0:空树。n > 0:存在一个根结点(唯一),根只有直接后继,没有直接前驱。其余结点划分成m (m >= 0)个互不相交的有限集合 T0, T1, …, Tm-1,每个集合都是一棵树,称为根的子树。
本质是递归——一棵树 = 一个根 + 多棵互不相交的子树。
相关概念
| 术语 | 含义 |
|---|---|
| 度(结点的度) | 该结点拥有的子树个数 |
| 叶结点 | 度 = 0 的结点 |
| 分支结点 | 度 ≠ 0 的结点 |
| 树的度 | 所有结点度的最大值 |
| 前驱 / 父结点 | 结点的直接前驱(除根外,每个结点有且仅有一个前驱) |
| 后继 / 孩子 | 结点的直接后继(可以有 0 或多个) |
| 兄弟 | 同一个父结点的孩子之间互为兄弟 |
| 祖先 / 子孙 | 父结点、爷结点…;孩子、孙、重孙… |
| 层次 | 根为第 1 层,根的孩子为第 2 层,依次类推 |
| 深度(高度) | 所有结点层次的最大值 |
| 森林 | m (m >= 0) 棵互不相交的树的集合 |
树的 3 条性质
- 除根结点外,每个结点有且仅有一个父结点。
n个结点的树有且仅有n - 1条边。- 任意两个结点之间有且仅有一条简单路径(无自环、无重边)。
二叉树
定义
每个结点最多两个子树(子树有左右之分,分别叫左孩子 / 右孩子、左子树 / 右子树)。
4 种遍历
- 先序(前序):根 → 左 → 右
- 中序:左 → 根 → 右
- 后序:左 → 右 → 根
- 层次:按层从左到右
由先序 + 中序或中序 + 后序可以唯一确定一棵二叉树。先序 + 后序不行。
满二叉树 vs 完全二叉树
- 满二叉树:深度
k,恰好2^k - 1个结点(每层都满)。 - 完全二叉树:深度
k,共n个结点,并且这n个结点位置和深度为k的满二叉树中编号1..n的结点一一对应。简言之:把一棵满二叉树从右往左、从下往上砍掉若干个结点,剩下的就是完全二叉树。
完全二叉树的特征:叶结点只可能出现在最下面两层。
二叉树的 6 条性质
下面
k= 树深度(根为第 1 层),n= 结点总数,n0 / n1 / n2= 度为0 / 1 / 2的结点数,i= 结点编号。
性质 1
二叉树第
i层最多2^(i-1)个结点(i >= 1)。
证明:归纳。
- 基础:
i = 1时只有根,最多1 = 2^0个。 - 归纳:假设第
i - 1层最多2^(i-2)个。又每个结点的度 ≤ 2,所以第i层最多 = 第i - 1层的2倍 =2 * 2^(i-2) = 2^(i-1)。
性质 2
深度为
k的二叉树最多2^k - 1个结点(k >= 1)。
证明:每层取性质 1 的上界相加:
1 + 2 + 4 + ... + 2^(k-1) = 2^k - 1
性质 3
对任意二叉树,叶结点数
n0= 度为 2 的结点数n2+ 1,即n0 = n2 + 1。
证明:
- 总结点数:
n = n0 + n1 + n2……(式 1) - 每个度为 1 的结点贡献 1 个孩子,每个度为 2 的结点贡献 2 个孩子:孩子总数 =
n1 + 2 * n2。 - 树中除了根,每个结点都恰好是某个结点的孩子:孩子总数 =
n - 1。
于是 n - 1 = n1 + 2 * n2,即
n = n1 + 2 * n2 + 1 ……(式 2)
(式 1)-(式 2):
n0 + n1 + n2 - (n1 + 2*n2 + 1) = 0
=> n0 = n2 + 1
性质 4
n个结点的完全二叉树深度 =floor(log2(n)) + 1。
证明:设深度为 k。按完全二叉树的定义:
- 前
k - 1层是满的(每层2^(i-1)个),所以前k - 1层有2^(k-1) - 1个结点;第k层至少 1 个、最多2^(k-1)个。 - 因此
n > 2^(k-1) - 1(前k-1层还没装满)。 - 同时
n <= 2^k - 1(深度为k的满二叉树)。
联立:2^(k-1) - 1 < n <= 2^k - 1,加上 1 后等价于:
2^(k-1) <= n < 2^k
两边取 log2:k - 1 <= log2(n) < k。
k 是整数,所以 k = floor(log2(n)) + 1。
性质 5
n个结点的二叉树,深度至少为log2(n + 1)(即floor(log2(n)) + 1,由ceiling(log2(n+1)) = floor(log2(n)) + 1)。
证明:性质 2 的逆命题。
性质 2 给出上界:深度 = k ⇒ n <= 2^k - 1 ⇒ 2^k >= n + 1 ⇒ k >= log2(n + 1)。
深度是整数,所以 深度 >= ceiling(log2(n + 1)),而 ceiling(log2(n + 1)) = floor(log2(n)) + 1。
性质 6
n个结点的完全二叉树,任一编号为i的结点:
- 父结点:若
i = 1则为根,无父结点;否则父结点编号为i / 2(整除)。 - 左孩子:若
2 * i > n则无左孩子;否则左孩子编号为2 * i。 - 右孩子:若
2 * i + 1 > n则无右孩子;否则右孩子编号为2 * i + 1。
证明:完全二叉树的编号规则是"自上而下、从左到右"。
- 同一层:结点
i和i + 1都在同一层。i的两个孩子占编号2i、2i+1;i+1的两个孩子占2(i+1) = 2i+2、2(i+1)+1 = 2i+3。2i+1 < 2i+2,编号不冲突。i/2(整除)正好是i的父——因为i的左孩子是2i、右孩子是2i+1,它们整除 2 都回到i。✓ - 跨层:结点
i是某层最后一个,下一层的第一个孩子是i + 1(不是2i+1)。i的父是i/2,但i+1的父不再是i+1 / 2,而是同一个父i/2的右孩子——因为从这一层跨到下一层时,编号是连续而非翻倍,规则parent = i / 2依然成立。✓
速查公式表
| 量 | 公式 |
|---|---|
第 i 层最多结点数 |
2^(i-1) |
深度 k 最多结点数 |
2^k - 1 |
n 结点完全二叉树深度 |
floor(log2(n)) + 1 |
| 叶结点数 vs 度 2 结点数 | n0 = n2 + 1 |
| 父 / 左 / 右孩子编号 | i/2,2i,2i+1(越界则不存在) |