堆排序伪码算法

时间:2014-06-26 15:23:09

标签: algorithm sorting data-structures heap heapsort

堆排序算法

n=m
for k:= m div 2 down to 0
    downheap(k);
repeat
    t:=a[0]
    a[0]:=a[n-1]
    a[n-1]:=t
    n—
    downheap(0);
until n <= 0  

有人可以向我解释在行中做了什么

    n=m
    for k:= m div 2 down to 0
        downheap(k);  

我认为这是堆构建过程,但for k:= m div 2 down to 0

的意思是什么

也是n项的数量。在数组表示中,最后一个元素存储在[n-1]? 但是为什么n> = 0.我们不能在n> 0完成。因为第一个元素会自动排序吗?

2 个答案:

答案 0 :(得分:2)

n=m
for k:= m div 2 down to 0
    downheap(k);

在二进制堆中,有一半节点没有子节点。因此,您可以通过从中点开始并向下筛选项目来构建堆。你在这里做的是从下往上构建堆。考虑这五个项目的数组:

[5, 3, 2, 4, 1]

或者,作为一棵树:

     5
  3     2
4   1

长度为5,所以我们想从索引2开始(假设一个基于1的堆数组)。然后,downheap将查看标记为3的节点,并将其与最小的子节点进行比较。由于1小于3,我们交换项目给出:

     5
  1     2
4   3

由于我们达到了叶级,我们已完成该项目。转到第一个项目5。它小于1,所以我们交换项目:

     1
  5     2
4   3

但是项目5仍然比其子项大,所以我们进行另一次交换:

     1
  3     2
4   5

我们已经完成了。你有一个有效的堆。

用手工(用铅笔和纸)来构建一个更大的堆 - 比如10个项目是有益的。这将使您非常了解算法的工作原理。

为了以这种方式构建堆,如果数组索引从0或1开始并不重要。如果数组从0开始,那么你最后再调用downheap ,但这没有做任何事情,因为您尝试向下移动的节点已经是叶子节点。所以它效率稍低(对downheap的一次额外调用),但没有害处。

但重要的是,如果您的根节点位于索引1处,则使用n > 0而非n >= 0停止循环。在后一种情况下,您最终可能会在堆中添加虚假值并删除应该存在的项。

答案 1 :(得分:0)

for k:= m div 2 down to 0

这似乎是伪代码:

for(int k = m/2; k >= 0; k--)

或者可能

for(int k = m/2; k > 0; k--)

取决于&#34;降至0&#34;包容与否。

  

也是n项数?

最初,是的,但它会在n-行上减少。

  

我们不能在n> 0完成。因为第一个元素会自动排序吗?

是的,这实际上就是这样。一旦N在n-变为零,它就会在循环体的大部分时间内完成,因此在此之后until n <= 0终止之前执行的唯一事情是downheap(0);