(对
d
d
d叉堆的分析)
d
d
d叉堆与二叉堆很类似,但(一个可能的例外是)其中的每个非叶结点有
d
d
d个孩子,而不是仅仅
2
2
2个。
a. 如何在一个数组中表示一个
d
d
d叉堆?
b. 包含
n
n
n个元素的
d
d
d叉堆的高度是多少?请用
n
n
n和
d
d
d表示。
c. 请给出EXTRACT-MAX在
d
d
d叉最大堆上的一个有效实现,并用
d
d
d和
n
n
n表示出它的时间复杂度。
d. 给出INSERT在
d
d
d叉最大堆上的一个有效实现,并用
d
d
d和
n
n
n表示出它的时间复杂度。
e. 给出INCREASE-KEY(
A
,
i
,
k
A, i, k
A,i,k)的一个有效实现。当
k
<
A
[
i
]
k < A[i]
k<A[i]时,它会触发一个错误,否则执行
A
[
i
]
=
k
A[i] = k
A[i]=k,并更新相应的
d
d
d叉最大堆。请用
d
d
d和
n
n
n表示出它的时间复杂度。
解
a.
与二叉堆类似,
d
d
d叉堆的元素也按照从上到下,从左到右的顺序在数组中排列。对于一个
d
d
d叉堆,第
1
1
1层有
1
1
1个元素,第
2
2
2层有
d
d
d个元素,第
3
3
3层有
d
2
d^2
d2个元素……。
下面推导数组中每个元素的父结点下标和子结点下标。对于
d
d
d叉堆中第
i
i
i层的第
j
j
j个元素(
i
i
i和
j
j
j都从
1
1
1开始),假设它在数组中的下标为
P
(
i
,
j
)
P(i, j)
P(i,j),有
元素
P
(
i
,
j
)
P(i, j)
P(i,j)的父结点为第
i
−
1
i-1
i−1层的第
⌈
j
/
d
⌉
⌈j / d⌉
⌈j/d⌉个元素,该结点在数组中的下标为
元素
P
(
i
,
j
)
P(i, j)
P(i,j)的子结点在第
i
+
1
i+1
i+1层,并且第
k
k
k个子结点是第
i
+
1
i+1
i+1层的第
d
(
j
−
1
)
+
k
d(j-1)+k
d(j−1)+k个元素。用
C
H
I
L
D
d
(
i
,
j
,
k
)
{\rm CHILD}_d(i, j, k)
CHILDd(i,j,k)表示元素
P
(
i
,
j
)
P(i, j)
P(i,j)的第
k
k
k个子结点在数组中的下标,有
综上所述,假设
d
d
d叉堆中一个元素的数组下标为
i
i
i,将
i
i
i替换上面的公式中的
P
(
i
,
j
)
P(i, j)
P(i,j),得到该元素的父结点下标和子结点下标分别为
我们可以将
d
=
2
d = 2
d=2代入上面的公式,得到二叉堆的元素
i
i
i的父结点下标为
P
A
R
E
N
T
2
(
i
)
=
⌊
i
/
2
⌋
{\rm PARENT}_2 (i)=⌊i / 2⌋
PARENT2(i)=⌊i/2⌋,左孩子结点下标为
L
E
F
T
(
i
)
=
C
H
I
L
D
2
(
i
,
1
)
=
2
i
{\rm LEFT}(i)={\rm CHILD}_2 (i,1)=2i
LEFT(i)=CHILD2(i,1)=2i,右孩子结点下标为
R
I
G
H
T
(
i
)
=
C
H
I
L
D
2
(
i
,
2
)
=
2
i
+
1
{\rm RIGHT}(i)={\rm CHILD}_2 (i,2)=2i+1
RIGHT(i)=CHILD2(i,2)=2i+1。这与6.1节给出的二叉堆公式完全一样,二叉堆只是
d
d
d叉堆的一个特例。
如果数组下标从
0
0
0开始,上面
2
2
2个公式应当变为
b.
高度为
h
h
h的
d
d
d叉堆,最少元素个数和最多元素个数分别为
所以,高度为
h
h
h的
d
d
d叉堆的元素个数
n
n
n满足以下不等式
将上面的不等式乘以
d
−
1
d-1
d−1得到
上面的不等式表明
(
d
−
1
)
n
(d-1)n
(d−1)n位于区间
[
d
h
,
d
h
+
1
−
1
]
[d^h, d^{h+1}-1]
[dh,dh+1−1]内。在这个区间范围内,有
⌊
l
o
g
d
(
(
d
−
1
)
n
)
⌋
=
h
⌊{\rm log}_d ((d-1)n)⌋=h
⌊logd((d−1)n)⌋=h。所以,包含
n
n
n个元素的
d
d
d叉堆的高度为
⌊
l
o
g
d
(
(
d
−
1
)
n
)
⌋
⌊{\rm log}_d ((d-1)n)⌋
⌊logd((d−1)n)⌋。
我们也可以将
d
=
2
d = 2
d=2代入上面的高度公式,得到二叉堆的高度为
⌊
l
g
n
⌋
⌊{\rm lg}n⌋
⌊lgn⌋。这与练习6.1-2的结论完全一样。
c.
先给出
d
d
d叉最大堆的D-MAX-HEAPIFY,与二叉最大堆是类似的。
每次递归调用D-MAX-HEAPIFY需要进行
d
d
d次比较,而递归的次数最多等于堆的高度
h
h
h。因此D-MAX-HEAPIFY的时间复杂度为
O
(
d
h
)
=
O
(
d
⌊
l
o
g
d
(
(
d
−
1
)
n
)
⌋
)
=
O
(
d
l
o
g
d
n
)
O(dh)=O(d⌊{\rm log}_d ((d-1)n)⌋)=O(d{\rm log}_d n)
O(dh)=O(d⌊logd((d−1)n)⌋)=O(dlogdn)。
下面给出
d
d
d叉最大堆的D-HEAP-EXTRACT-MAX。
D-HEAP-EXTRACT-MAX的运行时间取决于D-MAX-HEAPIFY,时间复杂度也为
O
(
d
l
o
g
d
n
)
O(d{\rm log}_d n)
O(dlogdn)。
d.
D-MAX-HEAP-INSERT的运行时间取决于D-HEAP-INCREASE-KEY,时间复杂度为
O
(
l
o
g
d
n
)
O({\rm log}_d n)
O(logdn)。
e.
D-HEAP-INCREASE-KEY中的while迭代次数最多等于堆的高度,因此它的时间复杂度为
O
(
l
o
g
d
n
)
O({\rm log}_d n)
O(logdn)。
以下是本题的代码链接。
https://github.com/yangtzhou2012/Introduction_to_Algorithms_3rd/tree/master/Chapter06/Problem_6-2