基数排序基于数据状况,这里考虑正数数组,根据数组中最大数的位数确定进桶的次数,比如先排个位,个位数字的范围是0~9,只需要一个长度为10的桶,桶的下标代表个位数字的大小,桶的值代表该下标出现过的次数。通过桶首先将数根据个位排好序然后倒出,将处理过的数再进桶,根据十位排序...周而复始处理到最高位,此时数组有序。
private static void radixSort(int[] arr) {
if (arr.length < 2 || arr == null){
return;
}
radixSort_r(arr,0,arr.length-1,maxbit(arr));
}
//求一个数组中最大的元素位数
private static int maxbit(int[] arr){
if (arr == null || arr.length == 0){
return -1;
}
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (arr[i]> max){
max = arr[i];
}
}
int res = 0;
while (max != 0){
max /= 10;
res++;
}
return res;
}
//求一个数某位上的数值
private static int getDigitNum(int num,int diget){
//个位diget/1,十位diget/2
return (num/(int) (Math.pow(10,(diget-1)))) % 10;
}
//基数排序
private static void radixSort_r(int[] arr, int l,int r,int diget){
//辅助数组
int[] help = new int[r-l+1];
//词频范围0~9
final int range = 10;
//最大位数有几位出入桶几次
for (int term = 1; term <= diget; term++) {
//每个位上数的频率数组
int[] bucket = new int[range];
for (int index = l; index <= r; index++) {
int num = getDigitNum(arr[index],term);
bucket[num] ++;
}
//生成频率的累加数组,0位置不变
for (int i = 1; i < bucket.length; i++) {
bucket[i] = bucket[i - 1] + bucket[i];
}
//倒序遍历原数组
for (int j=r; j >= l; j--){
//取出数组中对应位上的值
int num = getDigitNum(arr[j], term);
//累加数组中下标为该值的值恰好是按该位排序的那个顺序位置
//累加数组中存的是个数,对应到辅助数组下标要-1
//同时一个位置定好后,累加数组中对应下标的值要--
help[--bucket[num]] = arr[j];
}
for (int k = 0; k < help.length; k++) {
arr[l+k] = help[k];
}
}
}