實現多關鍵字排序通常有兩種作法:
最低位優先法(LSD)
先對K[0]{基數的最低位}進行排序,並按 K(0) 的不同值將記錄序列分成若干子序列之後,分別對 K[1] 進行排序,..., K[d-1]依次類推,直至最後對最次位關鍵字排序完成爲止。
最高位優先法(MSD)
先對 K[d-1]{基數的最高位}進行排序,然後對 K[d-2]進行排序,依次類推,直至對最主位關鍵字 K[0] 排序完成爲止。
百度百科對基數排序做了如下介紹:
基數排序(radix sort)是屬於“分配式排序”(distribution sort),基數排序法又稱“桶子法”(bucket sort),顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配至某些“桶”中,藉以達到排序的作用,基數排序法是屬於穩定性的排序,在某些時候,基數排序法的效率高於其它的穩定性排序法。
鏈式基數排序基本步驟如下
1.將待排序記錄以數組存儲[或者以指針相鏈,構成一個鏈表]
2.”分配”時,按當前”關鍵字位”所取值,將記錄分配到不同的”鏈表/鏈隊列”(即不同的桶或堆中)中,每條鏈表中記錄的”關鍵字位”相同;
3.”收集”時,按當前關鍵字位取值從小到大(即將這n條鏈表(n的大小爲基數的大小)按照編號, 依次將其中所有的元素取出)將各鏈表中的元素取出放入到原先的數組或鏈表中;
4.對每個關鍵字位均重複 2) 和 3) 兩步n次。
如採用LSD對{179, 208, 306, 93, 859, 984, 55, 9, 271, 33}(構成一個鏈表或者是數組)進行基數排序:
[第一步:按個位排]
[第二步:按十位排]
[第三步:按百位排]
代碼實現(以LSD爲例):
- //尋找數組中最大數字的位數
- template <typename Type>
- unsigned int maxBits(Type *begin, Type *end)
- {
- unsigned int bits = 1;
- //standard作爲基準, 如果array中的元素
- //大於standard, 則bits+1
- int standard = 10;
- for (Type *current = begin; current != end; ++current)
- {
- while (*current >= standard)
- {
- standard *= 10;
- ++ bits;
- }
- }
- return bits;
- }
- /**說明:
- begin:數組起始
- end:數組結尾
- radix:基數
- */
- #define DEBUG
- template <typename Type>
- void radixSort(Type *begin, Type *end, int radix)
- {
- //找到數組中最大數字的位數
- int bits = maxBits(begin, end);
- //基數爲radix, 則需要radix個鏈表
- std::list<Type> lists[radix];
- // 需要循環bits次
- for (int d = 0, factor = 1; d < bits; ++d, factor*=10)
- {
- //分配...
- for (Type *current = begin; current != end; ++current)
- {
- //取出相應位置上的數 (比如個位是1)
- int number = ((*current)/factor)%10;
- //則需要將之放到(分配到)標號爲1的鏈表中
- lists[number].push_back(*current);
- }
- //收集...
- Type *current = begin;
- //對radix個鏈表中的元素進行收集
- for (int i = 0; i < radix; ++i)
- {
- while (!lists[i].empty())
- {
- *current = lists[i].front();
- ++ current;
- lists[i].pop_front();
- }
- }
- #ifdef DEBUG
- //打印排序的中間結果
- for (current = begin; current != end; ++ current)
- {
- cout << *current << ' ';
- }
- cout << endl;
- #endif // DEBUG
- }
- }
- template <typename Type>
- void radixSort(Type *array, int arraySize, int radix)
- {
- return radixSort(array, array+arraySize, radix);
- }
時間複雜度分析:
設待排序列爲n個記錄,d個關鍵碼,關鍵碼的取值範圍爲radix,則進行鏈式基數排序的時間複雜度爲O(d(n+radix)),其中,一趟分配時間複雜度爲O(n),一趟收集時間複雜度爲O(radix),共進行d趟分配和收集.
附-測試代碼:
- int main()
- {
- int array[10];
- for (int i = 0; i < 10; ++i)
- {
- array[i] = rand()%1000;
- }
- for (int i = 0; i < 10; ++i)
- {
- cout << array[i] << ' ';
- }
- cout << endl;
- radixSort(array, 10, 10);
- for (int i = 0; i < 10; ++i)
- {
- cout << array[i] << ' ';
- }
- cout << endl;
- return 0;
- }
原文地址:http://blog.csdn.net/zjf280441589/article/details/42609453