笔记
建堆的过程实际上是自底向上地对所有非叶结点调用MAX-HEAPIFY的过程。由于叶结点没有孩子,所以每一个叶结点都可以看是只包含一个元素的最大堆。而自底向上地调用MAX-HEAPIFY,是要保证在处理任意一个结点的时候,它的子树已经满足了最大堆性质,这是调用MAX-HEAPIFY的必要条件。
BUILD-MAX-HEAP的运行时间为
O
(
n
)
O(n)
O(n)。这一结果的推导过程可以参考书本上的描述,这里不做说明。
下图给出了一个构建最大堆的例子。
练习
6.3-1 参照图6-3的方法,说明BUILD-MAX-HEAP在数组A = <5, 3, 17, 10, 84, 19, 6, 22, 9>上的操作过程。
解
6.3-2 对于BUILD-MAX-HEAP中第2行的循环控制变量
i
i
i来说,为什么我们要求它是从
⌊
A
.
l
e
n
g
t
h
/
2
⌋
⌊A.length/2⌋
⌊A.length/2⌋到1递减,而不是从1到
⌊
A
.
l
e
n
g
t
h
/
2
⌋
⌊A.length/2⌋
⌊A.length/2⌋递增呢?
解
因为调用MAX_HEAPIFY(A, i)的先决条件是,结点
i
i
i的子树必须都已经满足最大堆条件。而节点
i
i
i的子树中的结点的下标都比
i
i
i要大,因此BUILD-MAX-HEAP中的循环控制变量
i
i
i必须是递减的。
6.3-3 证明:对于任一包含
n
n
n个元素的堆中,至多有
⌈
n
/
2
h
+
1
⌉
⌈n/2^{h+1}⌉
⌈n/2h+1⌉个高度为h的结点?
解
首先考虑叶结点,它们的高度
h
=
0
h = 0
h=0,根据练习6.1-7的结论,含有
n
n
n个元素的堆的叶子结点的个数为
n
−
⌊
n
/
2
⌋
=
⌈
n
/
2
⌉
=
⌈
n
/
2
0
+
1
⌉
n-⌊n/2⌋=⌈n/2⌉=⌈n/2^{0+1}⌉
n−⌊n/2⌋=⌈n/2⌉=⌈n/20+1⌉。因此命题对
h
=
0
h = 0
h=0是成立的。
下面把原始堆
H
0
H_0
H0中的叶结点去掉,剩下的元素仍然构成一个堆
H
1
H_1
H1,并且
H
1
H_1
H1中的叶结点就是
H
0
H_0
H0中高度为
1
1
1的结点。堆
H
1
H_1
H1的大小为
⌊
n
/
2
⌋
⌊n/2⌋
⌊n/2⌋,故
H
1
H_1
H1中的叶结点个数为
⌈
⌊
n
/
2
⌋
/
2
⌉
≤
⌈
n
/
2
2
⌉
⌈⌊n/2⌋/2⌉≤⌈n/2^2 ⌉
⌈⌊n/2⌋/2⌉≤⌈n/22⌉。即原始堆
H
0
H_0
H0中高度为
1
1
1的结点至多有
⌈
n
/
2
2
⌉
=
⌈
n
/
2
1
+
1
⌉
⌈n/2^2 ⌉=⌈n/2^{1+1}⌉
⌈n/22⌉=⌈n/21+1⌉个。因此,命题对
h
=
1
h = 1
h=1也是成立的。
下面把堆
H
1
H_1
H1中的叶结点去掉,剩下的元素也构成一个堆
H
2
H_2
H2,并且
H
2
H_2
H2中的叶结点就是
H
0
H_0
H0中高度为
2
2
2的结点。堆
H
2
H_2
H2的大小为
⌊
⌊
n
/
2
⌋
/
2
⌋
⌊⌊n/2⌋/2⌋
⌊⌊n/2⌋/2⌋(因为堆
H
1
H_1
H1的大小为
⌊
n
/
2
⌋
⌊n/2⌋
⌊n/2⌋,根据练习6.1-7的结论,堆
H
1
H_1
H1中的非叶结点个数为
⌊
⌊
n
/
2
⌋
/
2
⌋
⌊⌊n/2⌋/2⌋
⌊⌊n/2⌋/2⌋)。堆
H
2
H_2
H2中的叶子结点个数为
⌈
⌊
⌊
n
/
2
⌋
/
2
⌋
/
2
⌉
≤
⌈
n
/
2
3
⌉
⌈⌊⌊n/2⌋/2⌋/2⌉≤⌈n/2^3⌉
⌈⌊⌊n/2⌋/2⌋/2⌉≤⌈n/23⌉。即原始堆
H
0
H_0
H0中高度为
2
2
2的结点至多有
⌈
n
/
2
3
⌉
=
⌈
n
/
2
2
+
1
⌉
⌈n/2^3 ⌉=⌈n/2^{2+1}⌉
⌈n/23⌉=⌈n/22+1⌉个。因此,命题对
h
=
2
h = 2
h=2也是成立的。
… …
以此类推,在一个大小为
n
n
n的堆中,高度为
h
h
h的结点至多有
⌈
n
/
2
h
+
1
⌉
⌈n/2^{h+1}⌉
⌈n/2h+1⌉个。