在最大堆中(假设它由数组表示),堆顶(即堆中最大的值)与数组中的最后一个元素(即堆中最小的值之一)交换位置,然后移除最后一个元素,接着新的堆顶元素会与其他值交换位置以回到其正确的位置。
那么,为什么不直接移除堆顶元素,让其他元素“填补”堆呢?
那么,为什么不直接移除堆顶元素,让其他元素“填补”堆呢?
堆的关键属性之一是其底层的二叉树是一个完全二叉树(即每个除了最后一个层级必须完全“填满”)。这样,堆具有 O(lg N)
操作,因为我们只需要在每个 O(lg N)
层级修改一个元素。让我们看一个例子。
10
/ \
8 7
/ \ / \
5 6 4 3
8
/ \
6 7
/ \ / \
5 ? 4 3
当你看着堆的大小为N
的任何叶子元素时,你可以肯定地说它不是整个堆中最大的log N
个元素之一。但这就是你能说的全部。例如,如果你的树有256个元素,那么数组中的最后一个元素(或任何其他叶子元素)将在第9到第256位之间。明白了吗?它可能是256个元素中的第9个!把这样的元素称为“最小”的简直是荒谬的。平均而言,它不仅不是最小的,甚至离最小都很遥远。
同样,选择最后一个元素只是因为它是维护连续数组的最便宜的方式。如果你以其他方式实现了堆,比如通过链表树而不是数组,那么在移除根节点后恢复堆的最优方式可能会有所不同。