【问题标题】:Heapsort: Build max heap procedure explanationHeapsort: Build max heap 过程解释
【发布时间】:2019-05-23 21:26:14
【问题描述】:
我正在尝试理解使用堆排序对数组进行排序的代码
(参考 - https://www.sanfoundry.com/java-program-implement-heap-sort/)
“maxheap”函数使用此计算来获取节点的左右子节点(在多个不同的示例/站点中使用相同)
int left = 2*i;
int 右 = 2*i + 1;
上述的逻辑/推理是什么?
另外,在 heapify 函数中,maxheap fn 以 i = N/2 -> 0 调用
(例如,而不是 i = 0 到 N -1。)
关于为什么这样做的任何想法?
public static void heapify(int arr[])
{
N = arr.length-1;
for (int i = N/2; i >= 0; i--)
maxheap(arr, i);
}
【问题讨论】:
标签:
algorithm
heap
heapsort
minmax-heap
【解决方案1】:
上述的逻辑/推理是什么?
堆是一个二叉树,在一个从 1 开始的索引数组中,如下所示,要获取节点 i 的左子节点,您需要索引 2*i,而右子节点则需要索引 @987654323 @。
Array:
[1, 2, 3, 4, 5, 6, 7]
Binary tree:
1
/ \
2 3
/ \ / \
4 5 6 7
另外,在 heapify 函数中,maxheap fn 以 i = N/2 -> 0 调用
(例如,而不是 i = 0 到 N -1。)关于为什么这样做的任何想法?
maxheap 或max_heapify 函数是一个获取数组和索引i 作为输入以维护最大堆属性的过程。 max_heapify 的假设是节点 i 的左右子树是最大堆,但节点 i 可能违反最大堆属性(它可能小于其子节点)。
这意味着如果我们在所有数组元素上调用max_heapify,所有节点都将保持最大堆属性,我们应该得到一个最大堆。但是,如果我们从数组的开头(树的根)开始,我们不能假设左右子树已经是最大堆,因此我们需要从结尾(树的叶子)开始并走到开头。
此外,叶子没有孩子,所以它们已经是微不足道的最大堆,我们不需要对它们调用 max_heapify。在具有 n 个元素的堆中,子数组 [floor(n/2)+1..n] 中的节点是叶子,因此我们可以从 floor(n/2) 循环到 1 并仅在内部节点上调用 max_heapify。
对于从 0 开始的数组:
left(i): 2 * i + 1
right(i): 2 * i + 2
leaves: [floor(n/2)..n-1]
internal nodes: [0..floor(n/2)-1]