排序篇之堆排序

堆的定义:

堆实质上是满足如下性质的完全二叉树(要么左右孩子都有,要么有一个左孩子): 树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。关键字均不大于左右孩子称为小根堆,关键字均不小于左右孩子称为大根堆。

用大根堆排序的基本思想:

① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区;
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key;
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
……
直到无序区只有一个元素为止。

代码实现:

void heapAdjust(int* a,int i,int size) //堆调整
{
 int nChild;
 int nTemp;
 for(;2*i+1<size;i=nChild)
 {
  nChild=2*i+1;          //子结点的位置=2*(父结点位置)+1
  if(nChild<size-1 && a[nChild+1]>a[nChild]) //在左孩子和有孩子中选择较大的
   ++nChild;              
  if(a[i]<a[nChild])      //如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
  {
   nTemp=a[i];
   a[i]=a[nChild];
   a[nChild]=nTemp;
  }
  else
   break;
 }
}
void heapSort(int* a,int size)
{
 int temp;
 for(int i=size/2-1;i>=0;--i)   //size/2-1是最后一个非叶节点,此处"/"为整除
  heapAdjust(a,i,size); //大顶堆的初始化
 for(i=size-1;i>0;--i)      //第一个元素和最后一个元素进行交换
 {
  temp=a[i];
  a[i]=a[0];
  a[0]=temp;
  heapAdjust(a,0,i);     //缩小范围,重新建堆
 }  
}

堆排序是不稳定排序,时间复杂度最差、最好、平均都是O(n*logn)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值