堆排序

/*
算法名称:堆排序
时间:20180419
编写者:发烧的小龙虾
编写动机:很重要呗
*/
#include <bits/stdc++.h>
using namespace std;

/*建立大顶堆的过程,将数组的i~n这些元素建成大顶堆*/
/*已知a[i]~a[n]中,a[i]是根,除了a[i]其他元素均满足大顶堆定义,因为建堆的过程是自下而上进行的,也就是说进行到这一步,除了根节点之外,它的左子树和右子树肯定都已经建立好了,只需要将a[i]这个元素逐层进行比较大小就行,如果a[i]小于下面某一层的某个节点,就交换信息,但函数并未用到交换,而是巧妙的利用了一种算法来进行*/
void HeapAdjust(int a[],int i,int n)
{
   int k,temp;//k为试探点的下标,即为a[i]的左孩子或者右孩子下标,temp保存最初a[i]的值,因为a[i]会变动,因此要用temp来保存
   temp=a[i];//保存最初a[i]的值
   for(k=2*i;k<=n;k*=2)//k=2*i,此时k在a[i]的左孩子上,先要判断有没有右子树,如果有,是左边大还是右边大?k跳到大的那个子树上
   {
       if(k+1<=n&&a[k]<a[k+1])//如果右子树存在且右边大,k++,代表k跳到a[i]的右子树上,即此时k=2*i+1
           k++;
       if(a[k]>temp)//判断这个子树和temp的关系,注意这里是擂台赛,每轮比拼的时候看的是最初始的a[i],我是最初始a[i]一层一层的进行擂台赛,如果发现大于左右子树就退出擂台赛,只要有子树比a[i]大,就必须继续进行擂台赛,而这里没有交换,而是让a[i]=a[k],a[i]此时不再是最初始的根了,而是当前的根
       {
           a[i]=a[k];//a[i]表示当前的根,不是最初始的根了。当前的根变为a[k](因为a[k]更大)
           i=k;//然后i指针下移指向k,此时的a[i]为更新后的根,它又要和它的左右孩子进行比较,一直循环下去
       }
       else//如果发现比左右孩子中最大的那个还要大,就停止了,因为再往下也不可能有比a[i]更大的了,因为是从下往上建立的,除了最初始的a[i],越往上越大。
           break;
   }
   a[i]=temp;//最后一个a[i]就填回temp
}

/*堆排序算法,升序!*/
void HeapSort(int a[],int n)
{
    int i;
    for(i=n/2;i>=1;i--)//从n/2逆序,即从下往上建立大顶堆
        HeapAdjust(a,i,n);
    for(i=n;i>=2;i--)//每次都拿最后一个元素开刀,而且每轮循环之后,需要建堆的元素个数就会少一个(因为最后一个一定是最大的,我把大顶堆的根放到最后一个了),因此i从n开始循环到2
    {
        swap(a[1],a[i]);//每次都让他和最后一个元素交换
        HeapAdjust(a,1,i-1);//此时,最后一个元素一定是最大的,只用关心前n-1个元素就行了,相应的元素个数也在减少,编变成i-1了。这次这句话的意思是从第一个元素到i-1个元素进行建立大顶堆操作。
    }
}

int main()
{
    int a[100],i,n;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        HeapSort(a,n);
        for(i=1;i<=n;i++)
            printf("%d ",a[i]);
        printf("\n");
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值