堆排序

此文乃博主的朋友写的,在此十分感谢她

#include <cstdio>

int n,m,a[100005];    //建立大根堆,从小到大排序 
void add(int x,int t)    //往堆中添加节点 
{
a[t]=x;    //把新节点放在堆的最后 
//整理堆,使堆始终保持大根堆的性质 
while (t>1 && a[t/2]<a[t])    // 如果该节点不是堆的根,并且大于它的父亲节点,那么不符合大根堆的性质 
{                             //调整 
int tt=a[t/2];  a[t/2]=a[t];  a[t]=tt;    //和父亲节点交换 
t/=2;                                     //节点上移,继续调整 

//因为只有当儿子节点大于父亲节点时才交换,所以最后新节点一定大于它的两个儿子节点
// 当新节点小于父亲节点时停止交换
//这样就保持了大根堆的性质 
return;
}
void sort()        //开始堆排 
{        //每次把根和堆的最后一个节点交换
         //就是把根取出,暂存在最后,然后整理堆中剩下的节点,找出剩余节点中最大的 
         //因为是大根堆,每次取出的根节点都是剩余节点中最大的
         //所以下一次取出的节点肯定比上一次小 
//每次都把取出的根节点放在当前堆的最后
//所以最后数组从后往前是递减的
//所以大根堆排序是从小到大的 
int t;
while (m>1)    //当堆中只剩下一个节点时,不用再整理了 
{
int ls,rs,son,i=1;
// ls  左儿子下标  
// rs  右儿子下标
//son  要和当前节点交换的儿子下标  
while (i*2<=m)  //儿子还在当前堆的范围内 
{
ls=i*2;  rs=ls+1;  son=i;
if (a[ls]>=a[i])     //如果左儿子大于当前节点,交换 
 t=a[ls],  a[ls]=a[i],  a[i]=t,  son=ls;
if (rs<=m && a[rs]>=a[i])     //如果左又儿子大于当前节点,且右儿子没有超出当前堆的范围,交换 
 t=a[rs],  a[rs]=a[i],  a[i]=t,  son=rs;
if (i==son) //说明当前节点大于它的两个儿子节点 
 break;    //结束 
i=son;      //如果没有结束,说明还需要交换,继续 
}
int t=a[m];  a[m]=a[1];  a[1]=t;  m--;
//  把根结点放在当前堆的最后 ,减小堆的范围 
}
return;
}
int main()
{
int i,j,x;
scanf("%d",&n);
scanf("%d",&a[1]);  
for (i=2;i<=n;i++)
{
scanf("%d",&x);
add(x,i);

//添加完节点的堆是一个大根堆 
int t=a[n];  a[n]=a[1];  a[1]=t;  m=n-1;
//  把根结点放在当前堆的最后 ,减小堆的范围
sort();
for (i=1;i<=n;i++)
 printf("%d ",a[i]);
return 0;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值