基數排序(Radix sort)是一種非比較型整數排序算法,其原理是將整數按位數切割成不同的數字,然后按每個位數分別比較。由於整數也可以表達字符串(比如名字或日期)和特定格式的浮點數,所以基數排序也不是只能使用於整數。基數排序的發明可以追溯到1887年赫爾曼·何樂禮在打孔卡片制表機(Tabulation Machine)上的貢獻。
它是這樣實現的:將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然后,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數列就變成一個有序序列。
基數排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由鍵值的最右邊開始,而MSD則相反,由鍵值的最左邊開始。LSD的基數排序適用於位數小的數列,如果位數多的話,使用MSD的效率會比較好。MSD的方式與LSD相反,是由高位數為基底開始進行分配,但在分配之后並不馬上合並回一個數組中,而是在每個“桶子”中建立“子桶”,將每個桶子中的數值按照下一數位的值分配到“子桶”中。在進行完最低位數的分配后再合並回單一的數組中。
本文地址:http://www.cnblogs.com/archimedes/p/radix-sort-algorithm.html,轉載請注明源地址。
舉例
第一步
第二步
第三步
算法實現
// Completed on 2014.10.10 21:10 // Language: C99 // // 版權所有(C)codingwu (mail: oskernel@126.com) // 博客地址:http://www.cnblogs.com/archimedes/ #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[] = {288, 52, 123, 30, 212, 23, 10, 233}; 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個指針。