您的位置:首页 > 其它

堆排序

2017-10-30 09:37 204 查看
此文乃博主的朋友写的,在此十分感谢她

#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);

8bcf

//添加完节点的堆是一个大根堆 
int t=a
;  a
=a[1];  a[1]=t;  m=n-1;
//  把根结点放在当前堆的最后 ,减小堆的范围
sort();
for (i=1;i<=n;i++)
 printf("%d ",a[i]);
return 0;  

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: