1. 簡述
1.1 一般方法
計數排序的排序對象一般是整數。
假設待排序數組為 int array[], 數組長度為n。
第一步:開闢臨時數組,int tmp[],數組長度為n。int count,數組長度為10。
第二步:遍曆數組,得到最大數值的位元d,即後面需要d次排序。
第三步:根據個位進行排序,根據十位進行排序,···,根據d位進行排序。
對於根據i位進行排序,其中1<=i<=d
首先,統計array的所有元素在d位上的出現次數,儲存到int count[]中。
然後,根據count[]計算得到,array應該在tmp中的出現的最後的位置,即count[i]=count[i]+count[i-1], i>0。
接著,從後向前遍曆array,對於array[i],得到其位元在count的對應下標m(個位對應0,十位對應1,···),令tmp[count[m]--] = array[i]
上一步中之所以從後向前遍曆array,是因為count恰好儲存的是tmp中每個分組最後出現的位置。
最後,將tmp內容,複製到array中。
1.2 一個更加抽象的虛擬碼:
RADIX-SORT(A,d)
for i = 1 to d
使用一種穩定排序演算法對A中元素的第i位進行排序
1.3 位元的順序
基數排序的方式可以採用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由索引值的最右邊開始,而MSD則相反,由索引值的最左邊開始。
即,一個是從低位到高位,另一個是從高位到低位。
2. 複雜度
以簡述中的方法分析,統計次數時間為n,計算count時間為10,基數分配時間為n,基數回收時間為n,基本上是d*(3*n+10)。 當然可以有一些最佳化。但是基本上,複雜度是O(d*(n+radix)),其中radix是關鍵碼的取值範圍。空間複雜度是O(n+radix)。
穩定性屬於穩定的排序。注意,這裡的穩定性是必須的,即針對每個位元分別進行排序必須是穩定的,只有這樣,才能保證基數排序從高位開始還是從低位開始排序都是正確的。
3. 代碼
//輔助函數,求資料的最大位元
int maxbit(int data[],int n) {
int d = 1; //儲存最大的位元
int p =10;
for(int i = 0;i < n; i++) {
while(data[i] >= p) {
p *= 10;
d++;
}
}
return d;
}
//基數排序
void radixsort(int data[],int n) {
int d = maxbit(data,n);
int * tmp = new int[n];
int * count = new int[10]; //計數器
int i,j,k;
int radix = 1;
for(i = 1; i <= d; i++) { //進行d次排序
for(j = 0; j < 10;j++) //每次分配前清空計數器
count[j] = 0;
for(j = 0;j < n; j++) { //統計每個桶中的記錄數
k = (data[j]/radix)%10;
count[k]++;
}
for(j = 1;j < 10; j++) //將tmp中的位置依次分配給每個桶
count[j] = count[j-1] + count[j];
for(j = n-1;j >= 0;j--) { //將所有桶中記錄依次收集到tmp中
k = (data[j]/radix)%10;
count[k]--;
tmp[count[k]] = data[j];
}
for(j = 0;j < n;j++) //將臨時數組的內容複寫到data中
data[j] = tmp[j];
radix = radix*10;
}
delete [] tmp;
delete [] count;
}
4. 參考資料
維基百科-基數排序 http://en.wikipedia.org/wiki/Radix_sort