【问题标题】:Heap sort pseudo code algorithm堆排序伪代码算法
【发布时间】:2014-08-17 12:53:21
【问题描述】:

在堆排序算法中

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 也是项目数。那么在数组表示中,最后一个元素存储在 a[n-1] 中? 但是为什么要对 n> = 0 这样做。我们不能在 n>0 处完成。因为第一个元素会自动排序?

【问题讨论】:

    标签: algorithm sorting data-structures heap heapsort


    【解决方案1】:
    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 &gt; 0 而不是n &gt;= 0 停止循环。在后一种情况下,您很可能最终会在堆中添加虚假值并删除应该存在的项目。

    【讨论】:

      【解决方案2】:
      for k:= m div 2 down to 0
      

      这似乎是以下的伪代码:

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

      或者可能

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

      取决于“降到0”是否包含在内。

      n 也是项目数吗?

      最初,是的,但它在n- 线上递减。

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

      是的,这实际上就是发生的事情。一旦 N 在n- 处变为零,它就在循环体的大部分过程中,所以在此之后和until n &lt;= 0 终止之前唯一执行的是downheap(0);

      【讨论】:

      • :但是n=m for k:= m div 2 down to 0 downheap(k);如何创建堆
      • k=m/2 和 t:=a[0].k=m/2 不是有问题,只有数组索引以 1 开头才有效吗?如果以 0 开头那么它应该是 k=m-1/2 对吗?在这里,因为索引应该从 1 开始,所以 a[0] 不应该是 a[1],因为没有 0 索引
      • "k=m/2 仅在数组索引以 1 开头时才有效?" 不确定您所说的“有效”是什么意思。无论数组是否被索引,语句k = m/2 都会执行而不会崩溃。在任何情况下,大多数语言都从零开始索引,因此“因为没有 0 索引”通常是错误的。
      • :我认为使用 k=m/2 它会找到最后一个有孩子的节点。因此,例如在数组 5,3,1,9,8,2,4,7 中,最后一个具有子节点的节点是包含 9 的元素。然后 k=m/2=4 仅在索引为 9 时才给出元素从1开始对吗?如果索引从 0 开始,这应该是 k=m-1/2 ?
      最近更新 更多