文章目录
Tree 树
Definition 定义
树是 n ( n ≥ 0 ) n(n\ge0) n(n≥0) 个结点的有限集合,当 n = 0 n=0 n=0 时,称为空树。对于任意一棵树都有:
- 有且仅有一个根结点(root)
- 从根节点到其他结点有且只有一条路径(这是图论中对于树的定义,事实上,树是有向图的一种)
这是一种非递归的定义,而显然树是一种递归的结构,我们可以用递归的方式对树进行定义:
- 当 n ≥ 1 n\ge1 n≥1 时,其余结点可以分为 m > 0 m>0 m>0 个互不相交的有限集合 T 1 , T 2 , T 3 , … , T m T_{1},T_{2},T_{3},\dots,T_{m} T1,T2,T3,…,Tm,这些集合本身都是一棵树,并且称为根结点的子树
这样的递归结构具有以下的特点:
- 除了根结点之外的所有结点有且只有一个前驱结点
- 每个结点都有零个或者多个结点
Some Important Terminology 一些重要的概念
关于结点关系:
Terminology | Explanation |
---|---|
父结点(parent node) | 该结点的前驱结点称为该结点的父结点 |
子结点(children node) | 该结点的后继结点成为该结点的子结点 |
兄弟结点(sibling node) | 具有相同父结点的结点互为兄弟结点 |
关于结点的一些概念:
Terminology | Explanation |
---|---|
结点的度 | 一个结点的子结点的度,结点的最大度数是树的度数 |
分支结点(非终端结点) | 度数不为0的点 |
叶子结点(终端结点) | 度数为0的结点(即只有前驱结点,但是没有后继结点,从图论的角度来说,这样的结点入度(in degree)为1,出度(out degree)为0) |
关于树的一些概念:
Terminology | Explanation |
---|---|
结点的层次 | 从根结点开始是第一层(或者是第零层,取决于具体要求) |
结点的深度 | 从根结点开始,逐层累加 |
结点的高度 | 从最后一层开始,逐层累加 |
树的高度(同时也是树的深度) | 树的最大层数 |
从树的结点次序来看,还可以分为:有序树和无序树
Some Important 一些重要的性质
树具有一下基本的性质:
- 如果树的结点度数是 k k k ,则树的结点数量为: n = k + 1 n=k+1 n=k+1(考虑一个无环图,那么这个图的结点数量肯定是边数量加 1 1 1,而一个结点的一个度数对应一条边,所以结点数量就是总度数加 1 1 1)
- 度为 m m m 的树种第 i i i 层上至少有 m i − 1 m^{i-1} mi−1 个结点,
- 高度为 h h h,度为 m m m 的树至多有 n = 1 + m + m 2 + ⋯ + m h − 1 = ( m h − 1 ) / ( m − 1 ) n=1 + m + m^{2} + \dots + m^{h-1}=(m^{h}-1)/(m-1) n=1+m+m2+⋯+mh−1=(mh−1)/(m−1) 个结点,例如我们熟悉的二叉树的结点总数为 ( 2 h − 1 ) / ( 2 − 1 ) = 2 h − 1 (2^{h}-1)/(2-1)=2^{h}-1 (2h−1)/(2−1)=2h−1 个
- 有 n n n 个结点的 m m m 叉树的高度至少为 log m ( n ( m − 1 ) + 1 ) \log_{m}(n(m-1)+1) logm(n(m−1)+1)
Binary Tree 二叉树
Definition 定义
二叉树即树的度数为2,有左右子树之分,不能任意颠倒,通常类似一棵度为 2 2 2 的有序树,区别在于:
- 二叉树可以为 ∅ \varnothing ∅,但是度为 2 2 2 的有序树至少有 3 3 3 个结点
- 当一个结点只有一个孩子的时候,对于有序树的结点来说,无需区分左右,而对于二叉树来说,这个子结点必须区分左右,结点次序是确定的
一些特殊的二叉树:
- 满二叉树:树的每一层的结点数量都是该层的最大结点数量
- 完全二叉树:满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树。完全二叉树是根节点和分支结点的度都为 2 2 2 的树
Properties 性质
二叉树的性质:
- 非空二叉树的叶子结点数
n
0
n_{0}
n0 等于度为
2
2
2 的结点数
n
2
n_{2}
n2 加一,即:
n
0
=
n
2
+
1
n_{0}=n_{2}+1
n0=n2+1
证 明 : 由 树 的 性 质 有 : 结 点 总 数 N = 1 ⋅ n 1 + ⋯ + m ⋅ n m , 其 中 m 是 树 的 度 ( 即 结 点 最 大 度 数 ) 又 ∵ N = n 1 + ⋯ + n m ∴ 对 于 二 叉 树 , 有 { N = n 0 + n 1 + n 2 N = 0 ⋅ n 0 + 1 ⋅ n 1 + 2 ⋅ n 2 + 1 = n 1 + 2 ⋅ n 2 + 1 ∴ n 0 = n 2 + 1 \footnotesize \begin{aligned} &证明:\\ &由树的性质有:结点总数 N=1\cdot n_{1}+\cdots+m\cdot n_{m},其中 m 是树的度(即结点最大度数)\\ &又\because N=n_{1}+\cdots+n_{m}\\ &\therefore 对于二叉树,有 \begin{cases} &N=n_{0}+n_{1}+n_{2}\\ &N=0\cdot n_{0}+1\cdot n_{1}+2\cdot n_{2}+1=n_{1}+2\cdot n_{2}+1 \end{cases}\\ &\therefore n_{0}=n_{2}+1 \end{aligned} 证明:由树的性质有:结点总数N=1⋅n1+⋯+m⋅nm,其中m是树的度(即结点最大度数)又∵N=n1+⋯+nm∴对于二叉树,有{N=n0+n1+n2N=0⋅n0+1⋅n1+2⋅n2+1=n1+2⋅n2+1∴n0=n2+1 - 第 i i i 层最多有 2 i − 1 2^{i-1} 2i−1 个结点
- 高度为 h h h 的二叉树至多有 2 h − 1 2^{h} - 1 2h−1 个结点
二叉树的顺序存储
存储结点的顺序:
- 自上而下
- 从左到右
即,一层一层的存储,先存储第一层,也就是树根,在数组的第一个位置,然后从左到右存储下一层,以此类推,这样存储,则有:
- 结点 a [ i ] a[i] a[i] 的两个子结点的位置为 a [ 2 i + 1 ] , a [ 2 i + 2 ] a[2i+1],a[2i+2] a[2i+1],a[2i+2]
- 结点
a
[
i
]
a[i]
a[i] (如果i不等于
0
0
0)的父结点为
a
[
(
i
−
1
)
/
2
]
a[(i-1)/2]
a[(i−1)/2]
当然,你也可以从数组下标为1的位置开始存储,这样在下标计算的时候可以更加简单
采用顺序存储结构在存储满二叉树和完全二叉树的时候,空间利用率较高,既可以直接访问,又可以通过下标确定相关结点;但是最坏的情况下,一棵高度为 h h h,包含 h h h 个结点的二叉树需要占据 2 H − 1 2^{H}-1 2H−1 个存储单元。并且,顺序存储的二叉树不适合进行插入删除操作
二叉树的链式存储
typedef struct Node{
ElementType value;
Node* left;
Node* right;
Node(ElementType value_, left_ = NULL, right_ = NULL)
:value(value_), left(left_), right(right_){}
}Node;