桶排序——基数排序
Posted 不做油腻的中年大叔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了桶排序——基数排序相关的知识,希望对你有一定的参考价值。
一、回顾
桶排序是一种基于数据状况的排序,不基于比较
计数排序是基于这些数的范围大小的排序
基数排序是基于这些数的位数的排序
二、思路
获取待排序数组的最大数max
拿到此最大数的位数,就代表了这些数的最大位数
按照位数(个、十、百、千......)来进行所有数的排序
准备10个桶,分别是0~9位,桶中记的是个数
遍历所有的数,统计此位数有几个
将桶中的个数做处理,就知道了在原数组中的位置范围(见代码)
再次遍历数组,根据桶中的信息,来将原数组按位数有序的方式进行排序
三、代码
思路理解起来比较复杂,看看代码
public static void radixSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
// maxbits找出这些数的最高位数
radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
public static void radixSort(int[] arr, int begin, int end, int digit){
final int radix = 10;
int[] count = new int[radix]; // 10个桶,0~9位
int[] help = new int[end-begin+1];
int i = 0, j = 0;
for(int d = 1; d <= digit; d++){
for(i = 0; i < count.length; i++){
count[i] = 0; // 清空桶中的数据,方便下一轮迭代
}
for(i = begin; i <= end; i++){
j = getDigit(arr[i], d); // 找到arr[i]第d位对应的数
count[j]++;
}
// 处理统计,count[i]记录了这个位数是多少的数,在原数组中的位置范围
for(i = 1; i < count.length; i++){
count[i] = count[i] + count[i - 1];
}
/**
* 如果i每次从开头而不是结尾开始
* 而count每次都是从这个位数范围的最大数的位置开始赋值
* 所以如果次序已经按照之前位数排好,经过这一步应该正好在前一位上的结果倒序了
* 比如按照第一位排好后:10, 3, 3, 7, 8
* 如果i每次从头开始,经过第二位排好后:8, 7, 3, 3, 10
*/
for(i = end; i >= begin; i--){
j = getDigit(arr[i], d);
help[--count[j]] = arr[i];
}
//help数组任务结束
for(i = 0; i < help.length; i++){
arr[begin+i] = help[i];
}
}
}
public static int getDigit(int x, int d){
return ((x / ((int)(Math.pow(10, d - 1)))) % 10 );
}
public static int maxbits(int[] arr){
int max = Integer.MIN_VALUE;
int res = 0;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
}
while(max != 0){
res++;
max /= 10;
}
return res;
}
四、复杂度
实现上可以做到稳定,时间复杂度O(n),空间复杂度O(n)
以上是关于桶排序——基数排序的主要内容,如果未能解决你的问题,请参考以下文章