堆排序

在利用最小堆进行排序时,需要执行N次deleteMin操作。按照顺序,最小的元素先离开堆。通过将这些元素记录到第二个数组然后再将数组拷贝回来,我们得到N个元素的排序。由于每个deleteMin花费O(logN)时间,因此总的运行时间是O(NlogN)。
该算法的主要问题在于,它使用了一个附加的数组。因此,存储需求增加一倍。在某些实例中这可能是个问题。注意,将第二个数组复制回第一个数组的附加时间消耗只是O(N),这不可能显著影响运行时间,。这个问题是空间的问题。
避免使用第二个数组的聪明的方法是利用这样的事实:在每次deleteMin之后,堆缩小了1。因此,堆中最后的单元可以用来存放刚刚删去的元素。例如,设我们有一个堆,它含有6个元素。第一次deleteMin产生a1。现在该堆只有5个元素,因此可以吧a1放在位置6上。下一次deleteMin产生a2,由于该堆现在只有4个元素,因此把a2放在位置5上。
使用这种策略,在最后一次deleteMin后,该数组将以递减顺序包含这些元素。如果想将这些元素排成更典型的递增顺序,那么可以改变堆序性质使得父亲的元素的值大于儿子的值。这样就得到max堆。
下面这段代码使用一个max堆。不像二叉堆,二叉堆的数据是从数组下标1处开始,而此处堆排序的数组包含位置0处的数据。

/**
* Standard heapsort.
* /
tempalte <typename Comparable>
void heapsort(vector<Comparable> & a)
{
   for(int i=a.size()/2;i>=0;i--) /* buildHeap */
       percDown(a,i,a,size());
   for(int j=a.size()-1;j>0;j--)
   {   
       swap( a[0],a[j]);  /*deleteMax*/
       percDown(a,0,j);
   }
}
/**
* Internal method for heapsort.
*  i is the index of an item in the heap.
*  Returns the index of the left child.
* /
inline int leftChild( int i)
{  
    return 2*i+1;
}

/**
* Internal method for heapsort that is used in deleteMax and buildHeap.
* i is the position fron which to percolate down.
* n is the logical size of the binary heao.
* /
template< typename Comparable>
void percDown(vector<Comparable> & a, int i,int n)
{
   int child;
   Comparable tmp;
   for(tmp=a[i];leftChild(i)<n;i=child)
   {  
       child=leftChild(i);
       if(child!=n-1 && a[child] <a[child+1] )
           child++;
       if(tmp<a[child])
          a[i]=a[child];
       else
          break;
   }
   a[i]=tmp;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值