一、简介
基数排序不是比较排序,依赖于计数排序。假设待排序序列中最大数字有d位数字,基数排序首先将所有元素拆分成d个关键字,每个关键字是元素的每位上的数字,例如257,拆分成3个关键字,2,5,7,如果位数不够,用0补全。对每一位的关键字进行计数排序。
排序时有两种解决方案:
最高位优先法(MSD)(Most Significant Digit first)
最低位优先法(LSD)(Least Significant Digit first)
这里以LSD为例。
二、伪代码
radixSort(A,radix,d)
//A是待排序数组,radix是容器个数,d是数字位数
for i=1 to d
对第i位数字进行计数排序
三、代码实现
public static void radixSort(int[] A,int radix,int d){
//给一个缓存数组
int [] temp=new int[A.length];
//给出容器数组
int [] buckets=new int[radix];
//对每位关键字进行计数排序
int rate=1;
for(int i=0;i<=d;i++){
//将A中元素复制到temp中
System.arraycopy(A, 0, temp, 0, A.length);
//重新初始化buckets
Arrays.fill(buckets,0);
int subKey;
//计算第i位关键字并统计
for(int j=0;j<A.length;j++){
subKey = (temp[j] / rate) % radix;
buckets[subKey]++;
}
for(int j=1;j<radix;j++){
buckets[j]=buckets[j]+buckets[j-1];
}
for (int m =A.length - 1; m >= 0; m--) {
subKey = (temp[m] / rate) % radix;
A[--buckets[subKey]] = temp[m];
}
rate *= radix;
}
}
四、注意事项
1、当d比较大时,使用MSD效率更高
2、基数排序的基础是计数排序,因为计数排序是稳定的。
3、对每个关键字进行计数排序的时间复杂度是O(n+k),所以基数排序的时间复杂度是O(d(n+k))。
4、MSD基数排序是从最高位开始对序列进行分组,到最低位为止。但是其实现过程是和LSD基数排序不同的,排序过程中需要用到递归函数。首先统计所有元素最高位的关键字,如果某个关键字的个数大于1,需要对这些关键字所在的元素递归的统计下一位关键字,直到所有关键字的个数小于等于1,回溯收集数据。