高精度基數排序

若對一個大整數序列進行排序操作,設序列中元素個數爲 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;
}
發佈了50 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章