基數排序(Radix Sorting)是一種與其他排序算法完全不同的排序方法,其他的排序算法都是通過關鍵字之間的比較和移動來完成的,而基數排序則不需要比較,而是採用一種多關鍵字的思想。
什麼是多關鍵字的思想呢?
給定一組數據,我可以先按個位的大小對所有數進行排序,然後再按十位進行排序,一直到最高位,這樣就可以使整組數據變得有效,這樣從最低位開始的方法稱爲最低位優先(Least Significant Digit first)
反之,如果先從最高爲的關鍵字開始,最後再比較最低位,則稱之爲最高位優先(Most Significant Digit first)
排序過程如下圖:
經過一次放置和回收,得到的序列已經按個位有序了,接下來按照次低位再次進行放置和回收。
由此可以看出,如果一組序列中最大的數爲兩位數,則需要兩次的分配和收集,整個分配收集的次數與最大數的位數有關。
求最大位數:
int GetMaxBit(int* array,int size)
{
assert(array);
int base = 10;
int digits = 1;//至少是個位數
for(int i = 0;i < size;++i)
{
while(array[i] >= base)//只要有數大於base,則位數+1
{
++digits;
base *= 10;
}
}
return digits;
}
基數排序需要兩個輔助空間,一個是0~9號桶,另一個是計算定位的數組,定位數組是幹什麼的呢?就是記錄每個桶中的數據待會要放回原數組的哪個位置。
下面是代碼實現:
void RadixSort(int* array,int size)
{
assert(array);
int* buckets = new int[size];
int base = 1;
int maxbit = GetMaxBit(array,size);
for(int i = 0;i < maxbit;++i)
{
//統計0~9號桶中的個數
int counts[10] = {0};
for(int i = 0;i < size;++i)
{
int num = (array[i]/base)%10;
counts[num]++;
}
//定位數組
int start[10] = {0};
for(int i = 1 ;i < 10;++i)
{
start[i] = start[i - 1] + counts[i - 1];
}
//往桶裏扔
for(int i = 0;i < size;++i)
{
int num = (array[i]/base)%10;
int& pos = start[num];
buckets[pos] = array[i];
++pos;
}
memcpy(array,buckets,sizeof(int)*size);
base *= 10;
delete[] buckets;
}
}
時間複雜度:
基數排序的時間複雜度可以理解爲O(d*n),d爲序列中最大的位數,適用於n值很大,但是關鍵字較小的序列。