高精度基数排序

若对一个大整数序列进行排序操作,设序列中元素个数为 n,最大元素在十进制表示下的长度为 m,则快速排序的时间复杂度为 O(nmlog2n),此时对任意两个数的比对时间占 O(m)。在这里,对任意两个整型数的比较不再是常数时间复杂度的了。

但这时,我们可以发现相对于基于比较的排序而言,非基于比较的排序的优势显现出来了。尽管对于鸽巢排序、计数排序而言庞大的空间消耗使我们放弃了使用它们的可能,但时间复杂度和空间复杂度都为 O(nm) 的基数排序确实可以让我们的排序更快。事实上,就算是对于整型数而言,基数排序的时间复杂度和空间复杂度也都是 O(n) 的,只是常数略大而已。

基数排序是 m 次计数排序的结果。在每次的计数排序中,这些数以当前所设定的比对关键字为第一关键字,以这些数原来的位置为第二关键字排序,时间复杂度为 O(n),空间复杂度为 O(nm)。所以,计数排序是稳定的排序。这为基数排序的实施提供了可能。

对于一次基数排序操作,我们将其分解为 m+1 个状态,记为第 0 到第 m 个状态,第 i 个状态表示后 i 位有序且稳定的排序结果,即以后 i 位的值作为第一关键字,以这些数上一次排序后的位置作为第二关键字的排序结果。特别的,第 0 个状态为起始状态。对于第 i 个状态,我们可以通过将第 i-1 个状态的序列对其右起第 i 位进行计数排序得到。第 m 个状态即为最终排序的结果。由归纳法可知,这个排序方法是正确的。

代码如下:

#include"iostream"
#include"stdio.h"
#include"string.h"
#define MAX_M (0xF)
#define MAX_N (100005)
using namespace std;
char temp[MAX_M];
int array[MAX_N][MAX_M],length[MAX_N],n,temp_array[MAX_N][MAX_M],temp_length[MAX_N];
void countsort(int num)
{
    int sum[0xF];
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++)
        sum[array[i][num]]++;
    for(int i=1;i<10;i++)
        sum[i]+=sum[i-1];
    for(int i=n;i>0;i--)
    {
        for(int j=0;j<length[i];j++)
            temp_array[sum[array[i][num]]][j]=array[i][j];
        temp_length[sum[array[i][num]]--]=length[i];
    }
    memset(array,0,sizeof(array));
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<temp_length[i];j++)
            array[i][j]=temp_array[i][j];
        length[i]=temp_length[i];
    }
}
int main()
{
    memset(array,0,sizeof(array));
    int m=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>temp;
        length[i]=strlen(temp);
        if(length[i]>m)
            m=length[i];
        for(int j=0;j<length[i];j++)
            array[i][j]=temp[length[i]-j-1]-'0';
    }
    for(int i=0;i<m;i++)
        countsort(i);
    for(int i=1;i<=n;i++)
    {
        for(int j=length[i]-1;j>=0;j--)
            printf("%d",array[i][j]);
        if(i<n)
            printf(" ");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值