通过分为两部分对堆排序进行优化是多么好

Posted

技术标签:

【中文标题】通过分为两部分对堆排序进行优化是多么好【英文标题】:Ho good is this optimization to heapsort by dividing into 2 parts 【发布时间】:2019-04-15 20:57:08 【问题描述】:

我在考虑快速排序没有找到枢轴的确切中点。 任何寻找精确中点的努力都会减慢快速排序的速度,而且是不值得的。

那么是否有可能使用 heapsort 来实现它?这是否值得? 我选择堆排序是因为它可以在对数时间内找到下一个最大值/最小值。

如果我们把堆排序数组分成两部分。

1) In the left half, we find max heap. (n/2-1 comparisons)
2) In the right half, we find min heap. (n/2-1 comparisons)
3) While 
     (max in left half is < min in right half)
      -- swap max in left half with min in right half
      -- heapify the swapped elements in respective halves 
      (i.e. find next max in left half 
       & find next min in right half).      
        
    end while loop.

当这个循环结束时,我们有两个完全不相交的一半。 到目前为止没有比常规堆排序有任何改进。

1)我们可以在每一半中完成剩余的堆化(剩余元素最多为 log n/2)。 因此,任何位于正确一半的元素最多会堆积 log n/2 而不是 log n。

这是一项优化

其他优化可以是

2) 我们也许能够在每个不相交的一半中递归地应用这个(除法和同意)。 3)我们也可以从后续不相交的分区中排除中心 2 个元素,因为它们已经在它们的不变位置 例如1-16(n-1 次比较以找到最大值/最小值) 我们在第一步中有 1-7 和 8-16 分区 第二步可能有4个分区 (7 & 8 在不变的位置)(所以 n-3 比较找到最大/最小) 3 步可能有 8 个分区 在不变的位置还有另外 4 个元素。 所以 n-7 比较以找到每个分区中的最大值/最小值。

我正在尝试实现这一点, 但我想知道是否有人认为这种方法有任何理论上的优势,或者它没有好处。

对于已经排序的,我认为不会有交换 & 我们只是在随后的一半中继续寻找最大/最小 对于降序排序,我们看到所有元素都被交换和堆积,没有机会分割和同意。所以它会和普通堆排序一样好或一样坏。这可能是最坏的情况。

对于所有其他人,我们将在最大/最小交换停止后看到任何改进。

【问题讨论】:

最简单的了解方法(因为精确的分析看起来很棒):将您的算法与 Heapsort 进行基准测试。我敢打赌:总是慢。 【参考方案1】:

你有一个创建两个堆的 O(n) 传递。然后在最坏的情况下,您在两个堆中都有(n/2)*(log n/2) 替换。此时您已经完成了n*log(n/2) 操作,甚至还没有开始排序。您将需要另一个 n*log(n/2) 操作来完成排序。

将其与堆排序进行对比,堆排序具有创建单个堆的 O(n) 次传递,然后是 n*log(n) 操作以完成对数组的排序。

我认为构建两个大小为 n/2 的堆比构建一个大小为 n 的堆没有特别的优势。在最好的情况下,您拥有更复杂的代码,它们具有相同或更差的渐近复杂度,并且不太可能给您带来实际的性能提升。

【讨论】:

最坏的情况是数组已经按降序排序或者后半部分的所有元素都大于前半部分的所有元素,我们将一步移动所有 n 个元素。但我们也在 heapify() 对它们进行了处理,这意味着它们是已排序的。所以我们应该在 1 步中完成排序。我们可能需要对此进行检查。这使它成为 n*log(n) 最坏的情况。事情是 谢谢。我认为最坏的情况是所有元素都在 1 步中被洗牌,我们已经完成了排序。 (因为我们从右边取 min 并在左边堆化它,反之亦然)我看到的一个问题是:使用 2 个堆,我们无法跟踪元素如何打乱以及去向。我看到它执行 O(log2(n)) 迭代,或者如果我们排除中心元素但每次迭代中完成的工作执行 O(log2(n) -1) * (O(n) + heapify()) 唯一的希望是 heapify本身正在部分排序。因此,如果一步完成更多的工作,我们可能会发现 next 做的工作很少.. @WinterMelon 你说,“但我们也在对它们进行 heapify() 处理,这意味着它们已排序。”构建二进制堆与排序不同。将工作分散到多个较小的堆中不会改变正在完成的工作总量。 我同意。对于那个很抱歉。 Heapify() 只给出最大值而不是排序。所以我看不出这种方法有什么更好的。 . @WinterMelon Heapify 不仅仅提供最大值。它排列数组,使其按堆顺序排列。这不是排序的,但它不是随机的。见en.wikipedia.org/wiki/Binary_heap。

以上是关于通过分为两部分对堆排序进行优化是多么好的主要内容,如果未能解决你的问题,请参考以下文章

快速排序

快速排序基准元的选取及其优化

快速排序(Quick Sort)及优化

三种快速排序以及快速排序的优化

转载 | 三种快速排序算法以及快速排序的优化

堆排序