排序2 - 线性排序 - 杭电OJ -1425

排序算法的特性:

线性排序:计数排序

逆序数对:归并排序

第K大数:快速排序

排序算法复杂度的下限是O(nlogn),这是基于比较的排序方法。

而线性的复杂度是O(n),这是不通过比较而进行排序的方法。

我们需要明确知道序列中所有数的一个范围 r ,复杂度就是O(n + r)。

好吧这样还是比较抽象,以下面的栗子可以快速看懂。

这里是几个数字,需要对其进行排序,采用计数排序的办法,这么多数字都是0~9的数字,那么开一个数组,大小是数据的范围。本题数组大小为10,因为是0~9,10个数字。

然后统计序列中每个数字出现的次数,0出现0次,1出现了1次......

现在线性扫描一遍辅助数组,即可得到排序好的序列,整个过程只需两次线性扫描。

看一下杭电这道题:http://acm.hdu.edu.cn/showproblem.php?pid=1425

1.先定义一个arr存放输入的序列

2.定义一个辅助数组number,但是数据中有负数,所以将原区间整个向右平移,范围变成0~1000000,而平移的范围设定一个常量RANGE

3.然后输入数据,输入的同时,将数据放入“ 桶 ”内。这里我将辅助数组称为桶,比较形象。

4.然后对桶里面的数据进行遍历,遍历的同时将数据从小到大放回原来的数组

5.由于要从大到小排序,所以输出的时候从n-1开始倒着遍历

   本题有个坑,就是最后一个数字后面没有空格,而其余数字有空格!!!

6.有个点需要注意,就是,辅助数组每次都需要清零,这里使用memset函数,记得头文件加上 cstring。

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

const int MAXN = 1e6 + 10;
const int RANGE = 5e5;
int arr[MAXN];
int number[MAXN];

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(number,0,sizeof(number));
        for(int i = 0;i < n; ++i){
            scanf("%d",&arr[i]);
            number[arr[i] + RANGE]++;//把数字放进桶里面,记得要加上位移距离
        }
        //接下来就是要把从小到大的排序的数字放进原来的arr数组里面
        int index = 0;
        for(int i = 0; i < MAXN; ++i){//遍历number数组
            while(number[i]--){
                arr[index] = i - RANGE;
                index++;
            }
        }

        for(int i = n-1; i >= n - m; --i){
            if(i == n - m){  //这里有坑,最后一个数字不需要加空格其余的要加空格
                printf("%d",arr[i]);
            }else{
            printf("%d ",arr[i]);
            }
        }

        printf("\n");
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值