基数排序

发布时间 2023-07-06 17:33:13作者: pdpd_zaa

最近又有个奇奇怪怪的题目,数据为 \(n \le 1 \times 10^7\),并且还要用到排序,普通的排序肯定会超时,然后就发现了一种 \(O(n)\)

介绍

基数排序(Radix Sort)是桶排序的扩展,它是将整数按位数切割成不同的数字,然后按每个数位分别比较以此来排序。

说详细点,也就是将所有数字统一为同样的长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。然后从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

下面就用表格来做个详细的解释:

最开始的序列
214
135
413
435
533
345
532
421
654
431

既然从小到大排序,那么先排个位。

排完个位后
421
431
532
413
533
214
654
135
435
345

再排十位

排完十位后
413
214
421
431
532
533
135
435
345
654

最后再排百位

排完百位后
135
214
345
413
421
431
435
532
533
654

这便是最后的序列。

过程

1.查找数组a的最大值,并求出最大值的位数,作为循环的次数

2.统计所有数字某一位,用个桶 \(ct\) 来记个数。

3.然后做个前缀和ct[i]+=ct[i-1],那么每个数的某一位 \(x\) 的排名就应该在 \(ct[x-1]+1 \sim ct[x]\)

4.然后按照上一次排序的结果,利用 \(ct\) 逐一放进另一个数组,再赋值到原来数组上。

5.重复进行(2)(3)(4)的操作。

代码

int maxbit(int a[],int n){
    int maxx=0;
    for(int i=1;i<=n;i++){
        int s=0,p=a[i];
        while(p!=0){
            p=p/10;
            s++;
        }
        maxx=max(maxx,s);
    }
    return maxx;
}
void Radix_Sort(int a[],int n){
    int m=maxbit(a,n),g=1;
    for(int t=0;t<=m;t++){
        for(int i=0;i<=9;i++)
            ct[i]=0;
        for(int i=1;i<=n;i++){
            int p=(a[i]/g)%10;
            ct[p]++;
        }
        for(int i=1;i<=9;i++) ct[i]+=ct[i-1];
        for(int i=n;i>=1;i--){
            int p=(a[i]/g)%10;
            rak[ct[p]]=a[i];
			ct[p]--;
        }
        for(int i=1;i<=n;i++){
        	a[i]=rak[i];
        }
        g=g*10;
    }
}