若對一個大整數序列進行排序操作,設序列中元素個數爲 n,最大元素在十進制表示下的長度爲 m,則快速排序的時間複雜度爲 O(nm
但這時,我們可以發現相對於基於比較的排序而言,非基於比較的排序的優勢顯現出來了。儘管對於鴿巢排序、計數排序而言龐大的空間消耗使我們放棄了使用它們的可能,但時間複雜度和空間複雜度都爲 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;
}