8644 堆排序

思路:
堆排序利用大根堆的特性,即根节点为最大值,每一次将根节点移到数组后面,相当于每一次都在把大的值往后放,同时我们所需要考虑的范围也在不断减小,相当于分别在0 ~ last ,0 ~ last-1 , 0 ~ last-2,…0~1中找最大值

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;


//n是总结点数,x是当前需要堆化的结点
void singleheapify(int a[],int last,int x)//对一个结点进行堆化
{

   int max = x;//max存放(x和他的儿子共3个结点)全家人中的最大值
   int lch=2*x+1;//左儿子刚好就是这个
   int rch=2*x+2;//右儿子刚好就是这个

   if(a[max]<a[lch]&&lch<=last) max = lch;

   if(a[max]<a[rch]&&rch<=last) max = rch;//这一步千万千万不要加else
   /*结合上一步的if,这两个if其实是在找x和儿子三个人之间的最大值,找到了再去交换,
   否则我们交换了一边,另一边可能是不满足父亲值最大的*/

   if(max != x)//儿子比父亲大,要交换
   {
       swap(a[max],a[x]);
       
       singleheapify(a,last,max);/*以当前max指向的下标为父亲,
       继续看看符不符合大根堆的要求*/
   }

}

void allheapify(int a[],int last)//全部节点堆化
{

    int lastparent = (last-1) / 2;//找到最后一个非叶子节点的下标

    //从最后一个非叶子节点开始枚举,在这之前的结点全是有儿子的结点
    for(int j=lastparent;j>=0;j--)singleheapify(a,last,j);
}

void heapsort(int a[],int last)//堆排序重点部分!!!!!
{
    allheapify(a,last);//把原数组堆化,使其各节点都满足堆的要求

    for(int i=last;i>=1;i--)//枚举大根堆的最后一个结点,一直枚举直到1就结束,//
    {                       /*大根堆在不断减小,
                          相当于分别在0~last,0~last-1,0~last-2,......0~1中找最大值,
                         每一次将所找到的最大值放到数组后面*/
        for(int j=0;j<=last;j++) printf("%d ",a[j]);cout<<endl;

        swap(a[0],a[i]);/*生成了一个大根堆因此具有根节点值最大的性质,
        利用这个性质我们把根节点放数组最后*/

        singleheapify(a,i-1,0);/*,当前根节点已经发生变化,
        即不是最大值而是最后一个结点交换上来的,
        结合上一步,这两步相当于把0~i范围内的最大值移出去,
        减小大根堆规模,当前只考虑0~i-1范围内最大值,在新的范围里面再次构建大根堆*/
    }
}

int main()
{
   int n,a[500];
   scanf("%d",&n);
   for(int i=0;i<=n-1;i++) cin>>a[i];
   heapsort(a,n-1);
   for(int j=0;j<=n-1;j++) cout<<a[j]<<" ";

  return 0;
}

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 像素格子 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读