堆的 shift-down 学习笔记
1. 堆的概念
堆是一种基于完全二叉树的数据结构,其中每个父节点的键值大于或等于其子节点。对于最大堆,根节点存储的是堆中的最大值;而最小堆的根节点存储的是堆中的最小值。
堆可以用于排序、优先队列和贪心算法等场景。在堆的实现中,shift-down 是一种重要的操作,用于维护堆的性质。
2. shift-down 操作
shift-down 操作也被称为“下溯”或“下滤”,它是一种在堆中删除元素时使用的操作。
具体来说,当从堆中删除元素后,为了保证剩余元素仍然满足堆的性质,我们需要将删除元素的位置替换为堆中的最后一个元素。然后,我们可以通过 shift-down 操作将这个新元素下滤到它所属的位置,以保证堆依然满足最大堆或最小堆的性质。
下面是 shift-down 操作的伪代码:
Copy Codewhile (当前节点有左儿子) {
将 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 操作的实现原理和方法,我们可以更好地理解堆的工作原理,从而更好地运用堆来解决实际问题。