转自:http://blog.csdn.net/yabber0914/article/details/52279537
(一)基数排序的思想:
不直接比较数与数的大小。把待排序的整数按位分,分为个位,十位…..从小到大依次将位数进行排序。
实际上分为两个过程:分配和收集。
分配就是:从个位开始,按位数从小到大把数据排好,分别放进0–9这10个桶中;
收集就是:依次将0-9桶中的数据放进数组中
重复这两个过程直到最高位
(二)过程:
比如现在要排序 {400,31,53,72,6,29}
首先按个位的大小依次排序,排序结果如下:
按十位进行排序,结果如下:
按百位排序后,结果如下:
(三)代码如下:
public static void main(String[] args) {
int[] arr={1200,121,292,72,12,233,44};
radixSort(arr,10,4);
showArr(arr);
//12 44 72 121 233 292 1200
}
//基数排序
/**
* @param arr 待排序数组
* @param radix 基数(10,盒子个数)
* @param d 待排序中,最大的位数
* */
public static void radixSort(int[] arr,int radix,int d){
int length=arr.length;
int[] temp=new int[length];//用于暂存元素
int[] count=new int[radix];//用于记录待排序元素的信息,用来表示该位是i的数的个数
int divide=1;
for(int i=0;i<d;i++){
//重置count数组,开始统计下一个关键字
Arrays.fill(count,0);
//将arr中的元素完全复制到temp数组中
System.arraycopy(arr,0,temp,0,length);
//计算每个待排序数据的子关键字
for(int j=0;j<arr.length;j++){
int subKey=(temp[j]/divide)%radix;
count[subKey]++;
}
//统计count数组的前j位(包含j)共有多少个数
for(int j=1;j<radix;j++){
count[j]=count[j]+count[j-1];
}
//按子关键字对指定的数据进行排序,因为开始是从前往后放,现在从后往前读取,保证基数排序的稳定性
for(int j=arr.length-1;j>=0;j--){
int subKey=(temp[j]/divide)%radix;
count[subKey]--;
arr[count[subKey]] = temp[j];
//插入到第--count[subKey]位,因为数组下标从0开始
}
divide = divide * radix; // 1 10 100
}
}
(四)说明:
分配的时间复杂度为O(n)
收集的的时间复杂度为O(radix)
分配和收集共需要distance趟,
所以基数排序的时间复杂度为O(d(n+r))
我们可以看出,基数排序的效率和初始序列是否有序没有关联。
整数时长度10W以上,最大值100W以下效率最好。
比其他排序好在可以适用字符串,或者其他根据多个条件排序的场景,如日期(先按日排,月排,年排)。