heapify(int rootIndex) 是否只为以输入 rootIndex 为根的堆构建堆?

问题描述

所以 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 为根的堆中的任意错误。

它唯一能解决的问题是根太小——根的两个子树必须已经满足堆属性才能正常工作。