1、有向树:若有向图
D
D
D的基图是无向树,则称
D
D
D为有向树。
2、若有向树
T
T
T是平凡树,或
T
T
T中有一个顶点入度为
0
0
0,其余顶点入度为
1
1
1,则称
T
T
T为有根树。入度为
0
0
0的点称树根,入度为
1
1
1出度为
0
0
0的点称树叶,入度为
1
1
1出度不为
0
0
0的点称内点,内点和根统称分支点。树中点
v
v
v的层数定义为从树根到
v
v
v的路径(容易证明该路径必然存在)长度,层数最大的顶点的层数称树高。
3、设
T
T
T为一棵根树,
v
i
,
v
j
∈
V
(
T
)
v_i,v_j\in V(T)
vi,vj∈V(T),若
v
i
v_i
vi可达
v
j
v_j
vj,称
v
i
v_i
vi是
v
j
v_j
vj的祖先,
v
j
v_j
vj是
v
i
v_i
vi的后代;若
v
i
v_i
vi邻接到
v
j
v_j
vj,则称
v
i
v_i
vi是
v
j
v_j
vj的父亲,
v
j
v_j
vj是
v
i
v_i
vi的儿子;若
v
j
v_j
vj和
v
k
v_k
vk父亲相同,称
v
j
v_j
vj和
v
k
v_k
vk互为兄弟。
4、设
T
T
T是一棵根树,若将
T
T
T的同层数的顶点标上次序,则称
T
T
T为有序树。
5、设
T
T
T是一棵根树,若
T
T
T的每个分支点至多有
r
r
r个儿子,称
T
T
T为
r
r
r叉树;若每个分支点恰好有
r
r
r个儿子,称
T
T
T为
r
r
r叉正则树(proper tree)。
计算机里我们主要考虑的是”二叉树“,也就是有序的二叉根树。我们考虑它的诸多性质:
1、二叉树的第
i
i
i层上最多有
2
i
−
1
2^{i-1}
2i−1个节点,其中
i
≥
1
i\ge 1
i≥1。
证明:当
i
=
1
i=1
i=1时显然。设当
i
=
k
i=k
i=k时结论成立。则
i
=
k
+
1
i=k+1
i=k+1时,由于第
k
k
k层至多有
2
k
−
1
2^{k-1}
2k−1个节点,而每个节点最多两个孩子,所以第
k
+
1
k+1
k+1层最多
2
∗
2
k
−
1
=
2
(
k
+
1
)
−
1
2*2^{k-1}=2^{(k+1)-1}
2∗2k−1=2(k+1)−1个节点。由数学归纳法,结论成立。
2、高度为
k
k
k的二叉树最多含
2
k
−
1
2^k-1
2k−1个节点。
证明:由1,每一层我们取最大值,则高度为
k
k
k的二叉树最多含的节点数为
1
+
2
+
2
2
+
2
3
+
.
.
.
+
2
k
−
1
=
2
k
−
1
1+2+2^2+2^3+...+2^{k-1}=2^k-1
1+2+22+23+...+2k−1=2k−1个节点。
3、任何一个二叉树,如果含
n
0
n_0
n0个叶子节点,
n
2
n_2
n2个度为
2
2
2的节点,则必然有
n
0
=
n
2
+
1
n_0=n_2+1
n0=n2+1。这里的度指的是根树里的出度。
证明:设度为
1
1
1的节点个数为
n
1
n_1
n1,则二叉树节点总个数
n
=
n
0
+
n
1
+
n
2
n=n_0+n_1+n_2
n=n0+n1+n2,二叉树的边数为
n
1
+
2
n
2
n_1+2n_2
n1+2n2,由于在二叉树里,边数等于顶点数减
1
1
1,所以
n
0
+
n
1
+
n
2
=
n
1
+
2
n
2
+
1
n_0+n_1+n_2=n_1+2n_2+1
n0+n1+n2=n1+2n2+1所以
n
0
=
n
2
+
1
n_0=n_2+1
n0=n2+1。
定义:
1、满二叉树(full binary tree):深度为
k
k
k且含
2
k
−
1
2^k-1
2k−1个节点的二叉树。
2、完全二叉树(complete binary tree):将某个满二叉树按照层序遍历对每个节点编号。对于某个树,如果存在某个满二叉树,使得该树的
n
n
n个节点和满二叉树中编号为
1
1
1到
n
n
n的节点一一对应,称此树为完全二叉树。
性质:
一个具有
n
n
n个节点的完全二叉树的深度为
⌊
log
2
n
⌋
+
1
\lfloor \log _2 n\rfloor +1
⌊log2n⌋+1。
证明:设某完全二叉树深度为
k
k
k,则
2
k
−
1
−
1
<
n
≤
2
k
−
1
2^{k-1} -1 < n\le 2^k-1
2k−1−1<n≤2k−1,也可以写为
2
k
−
1
≤
n
<
2
k
2^{k-1}\le n < 2^k
2k−1≤n<2k,所以
⌊
log
2
n
⌋
=
k
−
1
\lfloor \log _2n\rfloor = k-1
⌊log2n⌋=k−1,所以
k
=
⌊
log
2
n
⌋
+
1
=
⌈
log
2
(
n
+
1
)
⌉
k=\lfloor \log _2n\rfloor +1=\lceil\log_2(n+1)\rceil
k=⌊log2n⌋+1=⌈log2(n+1)⌉。
接下来,对于含有
n
n
n个节点的完全二叉树,我们考虑它的亲子的下标的关系。为了研究二叉堆的方便,我们将编号变为从
0
0
0开始。
性质:
1、如果节点
i
i
i有左孩子,那么其左孩子的下标为
2
i
+
1
2i+1
2i+1,且
2
i
+
1
≤
n
−
1
2i+1\le n-1
2i+1≤n−1。如果节点
i
i
i有右孩子,那么其右孩子的下标为
2
i
+
2
2i+2
2i+2,且
2
i
+
2
≤
n
−
1
2i+2\le n-1
2i+2≤n−1。如果节点
i
i
i非根节点,则其父亲为
⌊
i
−
1
2
⌋
\lfloor \frac{i-1}{2}\rfloor
⌊2i−1⌋。
证明:数学归纳法。先证前两个性质。如果
i
=
0
i=0
i=0,显然成立。假设当
i
=
k
i=k
i=k时成立。对于
i
=
k
+
1
i=k+1
i=k+1时,由于
k
+
1
k+1
k+1有左孩子,所以节点
k
k
k也必然有左孩子,否则二叉树无法complete。既然节点
k
k
k的左孩子是
2
k
+
1
2k+1
2k+1,所以
k
+
1
k+1
k+1的左孩子是
2
k
+
1
+
2
=
2
(
k
+
1
)
+
1
2k+1+2=2(k+1)+1
2k+1+2=2(k+1)+1。由数学归纳法,结论成立。右孩子的情况类似可证。最后一条性质可以由前两条证明出来。
2、给定一个数组,对其堆化,时间复杂度是
O
(
n
)
O(n)
O(n)。
证明:首先考虑堆化是个什么样的过程。我们先对二叉堆的最后一层开始,每次从当前层到下面的层堆化每一个小部分,直到堆化到第一层即可。
先从倒数第一层开始,将最后的每个叶子看作一个小型的堆,那么这些元素都不需要percolate。再看倒数第二层,将此层每个节点连同它们的后代做堆化,则每个堆顶至多需要比较
2
2
2次,也就是分别和左右孩子各比较
1
1
1次。再看倒数第三层,每个堆顶要percolate down的话,最多需要比较
4
4
4次,也就是每次sift down一次,就要比较两次。一般地,倒数第
k
k
k层,就需要比较
2
(
k
−
1
)
2(k-1)
2(k−1)次。设二叉堆总共有
m
m
m层,则倒数第
k
k
k层最多有
2
m
−
k
2^{m-k}
2m−k个节点,所以堆化的时间复杂度为
T
(
m
)
=
2
m
∑
k
=
1
m
k
−
1
2
k
−
1
T(m)=2^m\sum_{k=1}^{m} \frac{k-1}{2^{k-1}}
T(m)=2mk=1∑m2k−1k−1设
s
=
∑
t
=
0
m
−
1
t
2
t
=
∑
t
=
1
m
−
1
t
2
t
s=\sum_{t=0}^{m-1} \frac{t}{2^t}=\sum_{t=1}^{m-1} \frac{t}{2^t}
s=t=0∑m−12tt=t=1∑m−12tt则
1
2
s
=
∑
t
=
0
m
−
1
t
2
t
+
1
=
∑
t
=
1
m
t
−
1
2
t
\frac{1}{2}s=\sum_{t=0}^{m-1} \frac{t}{2^{t+1}}=\sum_{t=1}^{m} \frac{t-1}{2^{t}}
21s=t=0∑m−12t+1t=t=1∑m2tt−1两式相减,得:
1
2
s
=
∑
t
=
1
m
−
1
1
2
t
−
m
−
1
2
m
s
=
∑
t
=
0
m
−
1
1
2
t
−
m
2
m
−
1
=
2
−
m
+
1
2
m
−
1
\frac{1}{2}s=\sum_{t=1}^{m-1}\frac{1}{2^t}-\frac{m-1}{2^m}\\s=\sum_{t=0}^{m-1}\frac{1}{2^t}-\frac{m}{2^{m-1}}=2-\frac{m+1}{2^{m-1}}
21s=t=1∑m−12t1−2mm−1s=t=0∑m−12t1−2m−1m=2−2m−1m+1所以
T
(
m
)
=
2
m
+
1
−
2
(
m
+
1
)
T(m)=2^{m+1}-2(m+1)
T(m)=2m+1−2(m+1)而
m
=
⌊
log
2
n
⌋
+
1
m=\lfloor \log _2 n\rfloor +1
m=⌊log2n⌋+1,所以时间复杂度是
O
(
n
)
O(n)
O(n),其中
n
n
n为二叉树节点数。
3、给定一个空堆,向其逐次添加
n
n
n个元素,则建堆过程复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
证明:显然第
k
k
k层元素percolate up的次数最多是
k
k
k,所以如果二叉堆有
m
m
m层,所花时间
T
(
m
)
=
∑
k
=
1
m
2
k
−
1
k
=
(
m
−
1
)
2
m
+
1
T(m)=\sum_{k=1}^{m}2^{k-1}k=(m-1)2^m+1
T(m)=k=1∑m2k−1k=(m−1)2m+1而
m
=
⌊
log
2
n
⌋
+
1
m=\lfloor \log _2 n\rfloor +1
m=⌊log2n⌋+1,所以时间复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)。