Algorithm 松散堆排序

Algorithm 松散堆排序,algorithm,heap,Algorithm,Heap,有没有人听说过这种堆修复技术:SloppyHeapSort?它使用了一种“草率”的筛选方法。基本上,它接受要修复的元素,将其移动到堆的底部(不将其与其子元素进行比较),方法是将其替换为较大的子元素,直到它到达底部。然后,调用sift up,直到它到达正确的位置。这使得lgn比较(在大小为n的堆中)刚好超过lgn 但是,这不能用于堆构造,只能用于堆修复。为什么会这样?我不明白如果你试图构建一个堆,为什么它不起作用。有一个线性时间算法来构建一个堆。我相信作者的意思是,使用这种方法来构建堆是没有效率和

有没有人听说过这种堆修复技术:SloppyHeapSort?它使用了一种“草率”的筛选方法。基本上,它接受要修复的元素,将其移动到堆的底部(不将其与其子元素进行比较),方法是将其替换为较大的子元素,直到它到达底部。然后,调用sift up,直到它到达正确的位置。这使得lgn比较(在大小为n的堆中)刚好超过lgn


但是,这不能用于堆构造,只能用于堆修复。为什么会这样?我不明白如果你试图构建一个堆,为什么它不起作用。

有一个线性时间算法来构建一个堆。我相信作者的意思是,使用这种方法来构建堆是没有效率和更好的算法存在的。当然,您可以通过使用所描述的策略逐个添加元素来构建堆—您可以做得更好

如果部署得当,该算法肯定可以用作堆构造算法的一部分。在构建堆的过程中,被修复的子EAP的根不是数组的开始,这会影响sift up的实现(当到达数组的当前元素时,它需要停止,而不是继续到堆的底部),这一事实稍微复杂一些

需要注意的是,该算法与标准堆修复算法具有相同的渐近性能;然而,它可能涉及较少的比较。在某种程度上,这是因为标准堆修复算法是在将堆的根(最大的元素)替换为堆数组中的最后一个元素后调用的

最后一个元素不一定是堆中最小的元素,但它很可能接近底部。交换后,标准算法将交换的元素向下移动到log2N次,每个步骤需要两次比较;因为元素可能属于堆的底部,所以大多数情况下会执行最大数量的比较。但偶尔,可能只进行两到四次比较

相反,“草率”算法首先将“洞”从堆的顶部移动到接近底部的某个位置(log2N比较),然后将最后一个元素向上移动,直到找到它的位置为止,这通常只需要几次比较(但在最坏的情况下,可能需要近log2N的比较)

现在,在
heapify
的情况下,堆修复不是使用子EAP中的最后一个元素执行的,而是使用从原始向量中提取的以前未看到的元素执行的。这实际上不会对平均性能分析造成太大的改变,因为如果您使用随机元素(而不是可能很小的元素)开始堆修复,那么筛选操作的预期数量仍然接近最大值。(堆的一半位于最后一级,因此随机元素需要最大筛选次数的概率为一半。)

虽然sloppy算法(可能)改进了元素比较的数量,但它增加了元素移动的数量。经典算法最多执行log2N交换,而sloppy算法至少执行log2N交换,再加上筛选期间的附加交换。(在这两种情况下,通过在知道新元素的实际位置之前不插入新元素,可以将交换改进为移动,从而将内存存储的数量减半。)


作为附言,我找不到任何关于你的“草率”算法的参考。总的来说,在询问建议的算法时,通常最好包含一个链接。

我同意,可以做得更好。但我也在想,这是否与这种草率的技术依赖于堆结构和通常的堆修复函数这一事实有关。如果它期望堆的形式已经相当正确,那就意味着它不能用来构造堆,对吗?不,我不这么认为。您可以使用该技术在任何堆中插入,因此可以使用它来构造堆。它通常被称为自底向上的heapsort。