最大堆化算法
Max Heapify Algorithm
我有点困惑。如果我有一个数组,我必须构建一棵树。为了比较 childern 我必须知道我的数组有多大,在这种情况下它的 N = 6 所以我必须将它除以 2 所以我得到 3。这意味着我必须从索引 3 开始比较parent 节点。如果 child 大于 parent 节点,那么我必须交换它,否则我不必交换。然后我转到索引 2 并与 parent 进行比较,如果 children 大于 parent 节点,那么我必须交换它。然后索引 1 我必须与 children 进行比较并在需要时交换它。所以我创建了一个最大堆。 但我不明白为什么我必须用 A[5] 交换 A1 with A[6] then A1。最后我没有得到最大堆我得到了最小堆? Heapify 是什么意思?
非常感谢我感谢每一个答案!
我的一个练习是通过填充数组和树表示来说明堆排序的步骤
堆排序是一个两阶段过程。在第一阶段,将数组转入堆中,最大值位于顶部 A[1]。这是用红色圈出的第一个转换。在此阶段之后,堆位于从索引 1 到 6 的数组中,最大值位于 A[1] 中的索引 1 处。
在第二阶段,我们对值进行排序。这是一个多步骤过程,我们从堆中提取最大值并将其放入排序数组中。
堆在数组的左边,会向左收缩。排序后的数组在数组的右边,向左边增长。
在每一步中,我们将包含堆的最大值的堆 A[1] 的顶部与堆的最后一个值交换。排序后的数组然后向左增长了一个位置。由于已经放入A[1]的值不是最大的,我们必须恢复堆。这个操作称为 max-heapify。经过此过程后,A[1] 包含堆中的最大值,其大小已减少一个元素。
通过反复提取堆中剩余的最大值,我们可以对数组中的值进行排序。
二叉树的画法很乱。它的大小应该在每一步都缩小,因为堆的大小在缩小。
堆数据结构的实现有很多,但其中一个是在谈论特定的 implicit binary heap. Heap-sort is done in-place, so it uses this design. Binary heaps require a compete binary tree,因此它可以表示为从数组构建的隐式结构:对于每个 A[n]
在 zero-based 数组中,
A[0]
是根;如果 n != 0
,A[floor((n-1)/2)]
就是 parent;
- 若
2n+1
在数组范围内,则A[2n+1]
为左child,否则为叶节点;
- 如果
2n+2
在数组范围内,那么A[2n+2]
就是对的child.
假设一个数组是,[10,14,19,21,23,31]
,使用上面的规则隐含地表示为同态,如,
这不遵循 max-heap 不变量,因此必须 heapify
,可能使用 Floyd's heap construction,它使用 sift down
并在 O(n)
中运行。现在你有一个堆和一个没有长度的排序数组,([31,23,19,21,14,10],[])
,(这都是隐式的,因为堆不占用额外的内存,它只是内存中的一个数组。)这个阶段堆的可视化,
我们弹出堆的最大元素,用sift up
恢复堆的形状。现在堆小了一个,我们已经获取了最大元素并将其不移位地存储到我们的数组中,([23,21,19,10,14],[31])
,
重复,([21,14,19,10],[23,31])
,
([19,14,10],[21,23,31])
,
([14,10],[19,21,23,31])
,
([10],[14,19,21,23,31])
,
堆大小为1,所以最终排序的数组为[10,14,19,21,23,31]
。如果使用 min-heap 和相同的算法,则数组将以另一种方式排序。
我有点困惑。如果我有一个数组,我必须构建一棵树。为了比较 childern 我必须知道我的数组有多大,在这种情况下它的 N = 6 所以我必须将它除以 2 所以我得到 3。这意味着我必须从索引 3 开始比较parent 节点。如果 child 大于 parent 节点,那么我必须交换它,否则我不必交换。然后我转到索引 2 并与 parent 进行比较,如果 children 大于 parent 节点,那么我必须交换它。然后索引 1 我必须与 children 进行比较并在需要时交换它。所以我创建了一个最大堆。 但我不明白为什么我必须用 A[5] 交换 A1 with A[6] then A1。最后我没有得到最大堆我得到了最小堆? Heapify 是什么意思?
非常感谢我感谢每一个答案!
我的一个练习是通过填充数组和树表示来说明堆排序的步骤
堆排序是一个两阶段过程。在第一阶段,将数组转入堆中,最大值位于顶部 A[1]。这是用红色圈出的第一个转换。在此阶段之后,堆位于从索引 1 到 6 的数组中,最大值位于 A[1] 中的索引 1 处。
在第二阶段,我们对值进行排序。这是一个多步骤过程,我们从堆中提取最大值并将其放入排序数组中。
堆在数组的左边,会向左收缩。排序后的数组在数组的右边,向左边增长。
在每一步中,我们将包含堆的最大值的堆 A[1] 的顶部与堆的最后一个值交换。排序后的数组然后向左增长了一个位置。由于已经放入A[1]的值不是最大的,我们必须恢复堆。这个操作称为 max-heapify。经过此过程后,A[1] 包含堆中的最大值,其大小已减少一个元素。
通过反复提取堆中剩余的最大值,我们可以对数组中的值进行排序。
二叉树的画法很乱。它的大小应该在每一步都缩小,因为堆的大小在缩小。
堆数据结构的实现有很多,但其中一个是在谈论特定的 implicit binary heap. Heap-sort is done in-place, so it uses this design. Binary heaps require a compete binary tree,因此它可以表示为从数组构建的隐式结构:对于每个 A[n]
在 zero-based 数组中,
A[0]
是根;如果n != 0
,A[floor((n-1)/2)]
就是 parent;- 若
2n+1
在数组范围内,则A[2n+1]
为左child,否则为叶节点; - 如果
2n+2
在数组范围内,那么A[2n+2]
就是对的child.
假设一个数组是,[10,14,19,21,23,31]
,使用上面的规则隐含地表示为同态,如,
这不遵循 max-heap 不变量,因此必须 heapify
,可能使用 Floyd's heap construction,它使用 sift down
并在 O(n)
中运行。现在你有一个堆和一个没有长度的排序数组,([31,23,19,21,14,10],[])
,(这都是隐式的,因为堆不占用额外的内存,它只是内存中的一个数组。)这个阶段堆的可视化,
我们弹出堆的最大元素,用sift up
恢复堆的形状。现在堆小了一个,我们已经获取了最大元素并将其不移位地存储到我们的数组中,([23,21,19,10,14],[31])
,
重复,([21,14,19,10],[23,31])
,
([19,14,10],[21,23,31])
,
([14,10],[19,21,23,31])
,
([10],[14,19,21,23,31])
,
堆大小为1,所以最终排序的数组为[10,14,19,21,23,31]
。如果使用 min-heap 和相同的算法,则数组将以另一种方式排序。