[Alg]排序算法之分布排序
作者:屎壳郎
日期:Aug 2021
版次:初版
简介: 分布排序是与归并排序截然相反的处理思路,归并排序是逐步融合归并,而分布排序是分组然后合并,再分组再合并,所以分布排序又称为“桶排序”、“基数排序”或“数排 序”。它基于键值数字特性字分类,从而避免了比较操作。
1、引言
假设要对52张扑克牌排序,定义牌面键值顺序:
A < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K A<2<3<4<5<6<7<8<9<10<J<Q<K A<2<3<4<5<6<7<8<9<10<J<Q<K
定义花色键值顺序:
♣ < ♢ < ♡ < ♠ \clubsuit<\diamondsuit<\heartsuit<\spadesuit ♣<♢<♡<♠
两张牌确定先后顺序的条件为(i)它的花色小于另一张,或者(ii)两个花色相同,但牌面值小于另一张。通常的排序方法类似于基数交换排序(见《[Alg]排序算法之交换排序》,先根据花色分成四堆,然后再根据牌面值调整每一堆中牌的顺序。
还有一种更快的方法处理这类排序!首先根据牌面值分成13堆,先对这13堆排好序,即 A < 2 < ⋯ < K A<2<\cdots<K A<2<⋯<K;然后再根据花色分为4堆。然后合并到一起就得到排好序的结果。这个方法乍一看不显然。在第二步按花色分类时,如果两张牌进入不同的堆,说明花色不一样,会根据花色排序;如果两张牌具有一样的花色,那在第一步分类时已经排好序。同样的思想也可以应用到数字或字母类型的任意字典序的排序上。
设 N N N个记录,分成 M M M堆,每个堆的容量要保证能容纳 N N N个记录,这就需要 M ( N + 1 ) M(N+1) M(N+1)的空间,这就是大部分人拒绝这个算法的原因。
2、基数排序
下面介绍一种基于键值的基数,采用链表法的排序算法,姑且称之为基数排序。下面举一个以10进制为基数排序的例子。
503 087 512 061 908 170 897 275 653 426 154 509 612 677 765 703 503\;087\;512\;061\;908\;170\;897\;275\;653\;426\;154\;509\;612\;677\;765\;703 503087512061908170897275653426154509612677765703
第一趟遍历,以个位数为基准分堆,结果如下:
完成后重新串连起来,见图中红色线(算法H):
第二趟遍历,以十位数为基准分堆,结果如下: