问题描述
所以 heapify 操作是这样的(假设我们正在讨论二进制最大堆)。
maxHeapify(int rootIndex){
int largestIndex = rootIndex;
int largest = heap[rootIndex];
if (largest < heap[leftChildindexOf(rootIndex)]){
largestIndex = leftChildindexOf(rootIndex);
}
if (largest < heap[rightChildindexOf(rootIndex)]){
largestIndex = rightChildindexOf(rootIndex);
}
if (largestIndex != rootIndex){
//Swap heap[rootIndex] & heap[largestIndex]
maxHeapify(largestIndex);
}
}
这个 heapify 操作有一个假设,除了可能在输入 rootIndex 处之外,所有地方都满足最大堆属性。 现在,考虑这样的场景,
6
/ \
5 4
/ \
7 6
/ \ / \
6 6 6 6
显然,在存在 5 的情况下违反了最大堆属性。
如果我们在以 5 为根的堆上运行 maxHeapify
,结果堆变成,
6
/ \
7 4
/ \
5 6
/ \ / \
6 6 6 6
然后 maxHeapify
函数递归地向下移动到现在以 5 为根的堆,最后变成,
6
/ \
7 4
/ \
6 6
/ \ / \
5 6 6 6
然而,在 7 处也违反了最大堆属性,但由于 maxHeapify
递归向下移动,因此它不会触及。
假设 maxHeapify(int rootIndex)
只会确保在所有递归调用结束时,以 rootIndex
为根的堆将满足 max heap 属性是否有效,但对于以根为根的堆则无话可说在parentIndexOf(rootIndex)
?
解决方法
那个 heapify 操作甚至比这还要少。它无法修复以 rootIndex
为根的堆中的任意错误。
它唯一能解决的问题是根太小——根的两个子树必须已经满足堆属性才能正常工作。