堆的 shift-down 学习笔记

1. 堆的概念

堆是一种基于完全二叉树的数据结构,其中每个父节点的键值大于或等于其子节点。对于最大堆,根节点存储的是堆中的最大值;而最小堆的根节点存储的是堆中的最小值。

堆可以用于排序、优先队列和贪心算法等场景。在堆的实现中,shift-down 是一种重要的操作,用于维护堆的性质。

2. shift-down 操作

shift-down 操作也被称为“下溯”或“下滤”,它是一种在堆中删除元素时使用的操作。

具体来说,当从堆中删除元素后,为了保证剩余元素仍然满足堆的性质,我们需要将删除元素的位置替换为堆中的最后一个元素。然后,我们可以通过 shift-down 操作将这个新元素下滤到它所属的位置,以保证堆依然满足最大堆或最小堆的性质。

下面是 shift-down 操作的伪代码:

Copy Code
while (当前节点有左儿子) { 将 minChild 指向左儿子 如果右儿子存在且右儿子的键值更大(或更小),则将 minChild 指向右儿子 如果当前节点的键值比 minChild 的键值小(或更大),则将当前节点和 minChild 交换 否则,退出 while 循环 }

3. 实例演示

假设我们有一个最大堆,包含如下元素:

Copy Code
[20, 14, 16, 8, 10, 9, 3, 2, 4, 1]

现在,我们要删除堆顶元素 20 并通过 shift-down 操作维护堆的性质。

首先,我们用堆中的最后一个元素 1 替换堆顶元素 20。此时,堆变成了:

Copy Code
[1, 14, 16, 8, 10, 9, 3, 2, 4]

接着,我们对堆顶元素进行 shift-down 操作,将它下滤到恰当的位置。具体来说,我们从根节点开始,找到左、右儿子中键值更大的那个节点,并与当前节点交换。这里,我们首先与左儿子 14 进行交换,得到:

Copy Code
[14, 1, 16, 8, 10, 9, 3, 2, 4]

接着,我们再比较堆顶元素 14 和其左、右儿子中的最大值 16,发现需要再进行一次交换。得到:

Copy Code
[16, 1, 14, 8, 10, 9, 3, 2, 4]

此时,堆的性质已经满足了,我们可以停止 shift-down 操作。

4. 总结

shift-down 操作是维护堆的重要步骤之一。它可以帮助我们在删除元素后保持堆的性质,以便于下一次操作。通过掌握 shift-down 操作的实现原理和方法,我们可以更好地理解堆的工作原理,从而更好地运用堆来解决实际问题。