对堆进行排序的最快方法(至少在理论上)是什么?

发布于 2024-07-06 00:47:26 字数 173 浏览 11 评论 0原文

堆是一个列表,其中以下条件适用:

l[i] <= l[2*i] && l[i] <= [2*i+1]

for 0 <= i << len(list)

我正在寻找就地排序。

A heap is a list where the following applies:

l[i] <= l[2*i] && l[i] <= [2*i+1]

for 0 <= i < len(list)

I'm looking for in-place sorting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

紫竹語嫣☆ 2024-07-13 00:47:26

只需使用堆排序即可。 它就位了。 这将是最自然的选择。

您也可以只使用您的堆并使用其他算法对其进行排序。 然后,您从排序列表中重新构建堆。 快速排序是一个很好的候选者,因为您可以确定它不会仅仅因为您的堆已经预先排序而以最坏情况的 O(n²) 顺序运行。

如果你的比较函数很昂贵,那可能会更快。 堆排序往往经常评估比较函数。

Just use heap-sort. It is in-place. That would be the most natural choice.

You can as well just use your heap as it and sort it with some other algorithm. Afterwards you re-build your heap from the sorted list. Quicksort is a good candidate because you can be sure it won't run in the worst-case O(n²) order simply because your heap is already pre-sorted.

That may be faster if your compare-function is expensive. Heap-sort tend to evaluate the compare-function quite often.

手心的温暖 2024-07-13 00:47:26

好吧,通过将数据放在堆中,您已经完成了堆排序的一半。 您只需要实现堆排序算法的第二部分。 这应该比在堆数组上使用快速排序更快。

如果您有勇气,可以尝试实施 smoothsort,对于接近排序的数据,它比堆排序更快。

Well you are half way through a Heap Sort already, by having your data in a heap. You just need to implement the second part of the heap sort algorithm. This should be faster than using quicksort on the heap array.

If you are feeling brave you could have a go at implementing smoothsort, which is faster than heapsort for nearly-sorted data.

荒人说梦 2024-07-13 00:47:26

对堆进行就地排序听起来像是堆排序的工作。

我认为内存是有限的,也许是一个嵌入式应用程序?

Sorting a heap in-place kind of sounds like a job for Heap Sort.

I assume memory is constrained, an embedded app, perhaps?

冷默言语 2024-07-13 00:47:26

既然你已经有了一个堆,你不能只使用堆排序的第二阶段吗? ? 它工作到位并且应该是好的和高效的。

Since you already have a heap, couldn't you just use the second phase of the heap sort? It works in place and should be nice and efficient.

吃兔兔 2024-07-13 00:47:26

对于就地排序,最快的方法如下。 请注意我的代码中的差一错误。 请注意,此方法给出了一个反转的排序列表,需要在最后一步中取消反转。 如果您使用最大堆,这个问题就会消失。

总体思路很简洁:将最小的元素(索引为 0)与堆中的最后一个元素交换,将该元素向下冒泡,直到恢复堆属性,将堆的大小缩小 1 并重复。

正如 David Mackay 演示的那样,这并不是非就地排序的绝对最快方法此处 - 您可以通过将一个更有可能是最小的元素放在堆的顶部而不是底部的元素来做得更好排。

时间复杂度是 T(n.log n) 最坏情况 - n 次迭代,可能有 log n (堆的高度)经历 while 循环。

for (int k=len(l)-1;k>0;k--){
swap( l, 0, k );
while (i*2 < k)
  {
int left = i*2;
int right = l*2 + 1;
int swapidx = i;
if ( l[left] < l[right] )
  {
    if (l[i] > l[left])
      {
    swapidx = left;
      }
  }
else
  {
    if (l[i] > l[right])
      {
    swapidx = right;
      }
  }

if (swapidx == i)
  {
    // Found right place in the heap, break.
    break;
  }
swap( l, i, swapidx );
i = swapidx;
  }}

// Now reverse the list in linear time:
int s = 0; 
int e = len(l)-1;
while (e > s)
  {
    swap( l, s, e );
    s++; e--:
  }

For in-place sorting, the fastest way follows. Beware of off-by-one errors in my code. Note that this method gives a reversed sorted list which needs to be unreversed in the final step. If you use a max-heap, this problem goes away.

The general idea is a neat one: swap the smallest element (at index 0) with the last element in the heap, bubble that element down until the heap property is restored, shrink the size of the heap by one and repeat.

This isn't the absolute fastest way for non-in-place sorting as David Mackay demonstrates here - you can do better by putting an element more likely to be the smallest at the top of the heap instead of one from the bottom row.

Time complexity is T(n.log n) worst case - n iterations with possibly log n (the height of the heap) goes through the while loop.

for (int k=len(l)-1;k>0;k--){
swap( l, 0, k );
while (i*2 < k)
  {
int left = i*2;
int right = l*2 + 1;
int swapidx = i;
if ( l[left] < l[right] )
  {
    if (l[i] > l[left])
      {
    swapidx = left;
      }
  }
else
  {
    if (l[i] > l[right])
      {
    swapidx = right;
      }
  }

if (swapidx == i)
  {
    // Found right place in the heap, break.
    break;
  }
swap( l, i, swapidx );
i = swapidx;
  }}

// Now reverse the list in linear time:
int s = 0; 
int e = len(l)-1;
while (e > s)
  {
    swap( l, s, e );
    s++; e--:
  }
浪漫之都 2024-07-13 00:47:26

一项一项地读取堆顶部的项目。 基本上你所拥有的是堆排序。

Read the items off the top of the heap one by one. Basically what you have then is heap sort.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文