给大家介绍通俗易懂的基数排序(作为后缀数组的基础)

基数排序

基数排序是一种很咸的东西
复杂度应该是O(最大数的位数*所有数的个数){为什么如此呢,听我接下来讲解}

原理:
从个位十位依次枚举到最大位,
建立一个数组count[i],
表示当前这个数的当前这一位上的数字在当前我们在这一位上的排序中的序数,
每一轮把当前这个数字的序数求出来,再按序数所代表的的顺序的数组去覆盖原数组

for example
15 82 633 15 46 13
按照个位排序
82
13 633
15 15
46
82 13 633 15 15 46
再按十位排序
(以为我们按上一次的顺序来排这一次)
13 15 15
46
633
82
13 15 15 46 633 82
再按百位排序
013 015 015
046
082
633
13 15 15 46 82 633
好了排完顺序了

bilingbiling
代码方式很多种但是如果大数据啊字符串啊容易空间卡爆,
但是我链表非常难受
所以先写了一个通俗易懂版本的基数排序

#include<bits/stdc++.h>
using namespace std;
int a[100010],n;
int maxx()
{
    int d=1,p=10;
    for(int i=1; i<=n; i++)
    {
        while(a[i]>=p)
        {
            p=p*10;
            d++;
        }
    }
    return d;
}

void f()
{
    int d=maxx();//去求位数,其实有更优的直接O(1)的求法
    int count[100]; // 计数
    int t[100010]; // 临时数组,用来覆盖原数组
    int s=1,i,j,k;
    for(i=1; i<=d; i++)
    {
        memset(count,0,sizeof(count));
        for(j=1; j<=n; j++)
        {
            k=(a[j]/s)%10; 
            count[k]++;//统计每个桶中的记录数
        }

        for(j=1; j<=9; j++)  count[j]+=count[j-1]; //统计桶中记录数的位置

        for(j=n; j>=1; j--)  //将桶中收集到的数依次收集到t中
        {
            k=(a[j]/s)%10;
            t[count[k]]=a[j];
            count[k]--;
        }
        for(j=1; j<=n; j++) //将临时数组的内容复制到a中
            a[j]=t[j];
        s=s*10;
    }
}


int main()
{
    int i;
    scanf("%d",&n);
    for(i=1; i<=n; i++) scanf("%d",&a[i]);
    f();
    for(i=1; i<=n; i++) printf("%d ",a[i]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/beautiful_cxw/article/details/81056602
今日推荐