radix sort 基数排序 和 counting sort 计数排序
ref: 算法导论
基数排序是按数据位进行排序的算法,并且基数排序从最低有效位进行排序。
排序过程:
1) 按照第i(i初始为0)位数值对数据进行排序,对于i位相同的数据,不改变这些数据的相对位置。
2) ++i,并重复上述操作,直到i等于数据的位数。
问题一,为何不从最高有效位进行排序?
从最高有效位排序时最直观的想法:先按最高有效位进行排序,将有相同有效位数值的数据划为一组,在组内递归应用算法:查看下一个有效位,继续分组。需要注意的是,这里需要保存大量的中间信息(需要保留分组信息)。
问题二,为何可以排序?
在排序过程中的不变量:如果算法已经过k位,则数据在K位上是有序的。
证明: 若数据在K位上已有序,经过算法,对K+1位进行排序,对于K+1位上数值相同的数据,由于数据在K位上已经有序,则排序成功,对于在K+1上有不同数值的数据,排序结果,排序顺序及代表数据在K位上的排序结果。因此不变量成立。
结束:当经过N位(数据总位数)时,数据在N位上有序,即排序成功。
问题三,应用?
比如对,年月日进行排序,应用radix sort,分别对日,月,和年进行一次排序即可。
==========================================================================
对于radix sort 每一位的排序,由于数值有限(比如十进制数只有0~9十种可能),非常适用于counting sort:
counting sort的核心想法:对于某个数值,知道有多少个数比它小,即可知道它排序后的位置。
算法的简单描述:
A[1, 2, ... , n]是要排序的数组,B[1, 2, ..., n]是输出数组,C[0, 1, 2, ..., K-1]是辅助数组,初始为全0。A中数值范围0 ~ (K-1)
for(int i = 1; i <= n; ++i) ++C[A[i]]; //得到每个值对应有几个数
for(int i = 1; i < k; ++i) C[i] = C[i] + C[i - 1]; //位置的右边界
for(int i = n-1; i >= 0; --i) {B[C[A[i]] - 1] = A[i]; --C[A[i]];} //按照边界放置数值
需要注意的是,如果值相同,counting sort会保持输入队列中数的顺序,有这种性质的排序又叫做 stable sort,即稳定排序,这也是radix sort选择它的另一个重要原因。