基數排序-C語言實現
基數排序(radix sorting)屬於“分配式排序”(distribution
sort),又稱“桶子法”(bucket sort)的穩定性排序法。基數排序的方式可以採用最低有效位LSD(Least
significant digital)或最高有效位MSD(Most significant digital)。LSD的排序方式將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零。
然後 從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後, 數列就變成一個有序序列。而MSD則相反,由最高位開始,先按最高位排序分組,同一組中記錄,最高位相等,再對各組按次高位排序分成子組,之後,對後面的位繼續這樣的排序分組,直到各子組排序完成。再將各組連線起來,便得到一個有序序列
0 90 100 20 90 0 100 3(3在排序前要填充為003)204
1 91 1
2 32
2 20
3 3 按最低位排序結果{90 100 20 90 91 32 3 204 94 56 48} 3 32 得到第二次排序結果{100 3 204 20 32 48 56 90 90 91 94}
4 204 94 -------------》 4 48 -------------------》
5
5 56
6 56 6
7 7
8 48 8
9 9 90 90 91 94
----------------------------------------------------------------------------------------------------------------------------------------------------------
0 3 20 32 48 56 90 90 91 94 {用0填充了最高位)
1 100
2 204
3 第三次排序結束(最高有3位數)
4 ---------------------------------> {3 20 32 48 56 90 90 91 94 100 204} 有序序列
5
6
7
8
9
LSD的基數排序適用於位數小的數列,如果位數多的話,使用MSD的效率會比較好。MSD的方式與LSD相反,是由高位數為基底開始進行分配,但在分配之後並不馬上合併回一個陣列中,而是在每個“桶子”中建立“子桶”,將每個桶子中的數值按照下一數位的值分配到“子桶”中。在進行完最低位數的分配後再合併回單一的陣列中,下一篇部落格會介紹。
C語言實現:(程式碼來自網際網路)
#include<stdio.h>
#include<stdlib.h>
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 = (int *)malloc(n * sizeof(int));
int *count = (int *)malloc(10 * sizeof(int)); //計數器
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++)
count[j] = count[j - 1] + count[j]; //第j個桶以及之前所有桶中元素的總數
for(j = n - 1; j >= 0; j--) { //將所有桶中記錄依次收集到tmp中
k = (data[j] / radix) % 10;
tmp[count[k] - 1] = data[j];
count[k]--;
}
for(j = 0; j < n; j++) //將臨時陣列的內容複製到data中
data[j] = tmp[j];
radix = radix * 10;
}
free(tmp);
free(count);
}
int main()
{
int a[] = {90,100,204,20,32,19,56,48,3,91,94,90};
int n;
n = sizeof(a) / sizeof(a[0]);
radixsort(a, n);
for(int k = 0; k < n; k++)
printf("%d ", a[k]);
printf("\n");
return 0;
}
時間效率:設待排序列為n個記錄,d個關鍵碼,關鍵碼的取值範圍為radix,則進行鏈式基數排序的時間複雜度為O(d(n+radix)),其中,一趟分配時間複雜度為O(n),一趟收集時間複雜度為O(radix),共進行d趟分配和收集。空間效率:需要2*radix個指向佇列的輔助空間,以及用於靜態連結串列的n個指標。