sdnu 1521(堆排序应用)

1521.排序

Time Limit: 1000 MS    Memory Limit: 32768 KB
Total Submission(s): 70    Accepted Submission(s): 24

Description

将输入的数从小到大排序。

Input

输入数据n(1<=n<=1000000)

接下来输入n个数据

(多组输入数据)

Output

按格式输出排序后的n个数。

Sample Input

5
5 3 4 6 8

Sample Output

3 4 5 6 8

Source

Unknown
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
int a[1000004];
void heapadjust(int a[],int i,int len)
{
    int lchild = i * 2;
    int rchild = i * 2 + 1;
    int mx = i;
    if(i <= len/2)
    {
        if(a[lchild] > a[mx]&&lchild <= len)
            mx = lchild;
        if(a[rchild] > a[mx]&&rchild <= len)
            mx = rchild;
        if(mx != i)
        {
            swap(a[mx], a[i]);
            heapadjust(a, mx, len);//防止交换后破坏子树的堆结构
        }

    }
}
void heapbuild(int a[],  int len)
{
    for(int i = len/2; i >= 1; i --)
    {
        heapadjust(a, i, len);
    }
}
void heapsort(int a[], int len)
{
    heapbuild(a, len);
    for(int i = len; i >= 1; i --)
    {
        swap(a[1],a[i]);
        heapadjust(a, 1, i - 1);
    }
}


int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        memset(a,0,sizeof(a));
        for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &a[i]);
    }
    heapsort(a,n);
    printf("%d", a[1]);
    for(int i = 2; i <= n; i ++)
    {
        printf(" %d", a[i]);
    }
    printf("\n");
    }
    return 0;
}
由小到大排序,构建大根堆,
由大到小排序,构建小根堆,
堆排序是一个主框架len次循环
每一次循环中找到堆中剩余元素的最大值,然后此时len的最后一个交换,这就相当于把元素按从大到小的顺序从后往前排。
每一次循环中,又要调用堆构建函数,调用堆构建函数的框架是len/2次循环,从下往上进行构建,每一次循环调用堆调整,但是要确保子树堆结构的不变。
平均性能
O(N*logN)。

堆排序其他性能

由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为O(1).
它是 不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)
性能资料参考https://baike.baidu.com/item/%E5%A0%86%E6%8E%92%E5%BA%8F/2840151?fr=aladdin
参考博客http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值