限制:非负数,能表达成10进制的数
时间复杂度:
O(N* log10max) max = 最大数的位数
如果是2 进制就是log 2
思路:
1 有10个桶(几进制就有几个桶)
2 有个一个数组arr,把所有数字按照个位数 大小放到1到10的桶里
3 然后按照桶的顺序取出数字,这样数字就按照个位数大小排好了
4 按照2和3的操作,再操作10位百位直到最高位
代码思路
由定位器直接能算出数组下标位置,优化了出桶的速度,节约了容器空间不需要10个队列,
我写的实现
package 算法;
public class 桶排序 {
/**
* 1 数组无负数
* 2 数组 为4位数
* @param arr
* @return
*/
public static int[] sort(int[] arr){
//1 获取最大位数
int ws = getMaxWs(arr);
// 2 循环 数字的位数
for (int i = 0; i < ws; i++) {
int[] fb = new int[11];
int helpArr[] = new int[arr.length];
//23循环数组 计算出 个位数分布
for (int j = 0; j < arr.length; j++) {
//获取 arr[j] 数字 第 i 位的数
int num = getws(arr[j], i);
fb[num]++;
}
// 4 完善fb 让 每个数字累加能算出 第几个数从数组下标几开始
for (int j = 1; j < fb.length; j++) {
fb[j]+=fb[j-1];
}
//5 根据分布 对数组进行排序
for (int k = arr.length-1; k >= 0; k--) {
//3.1 根据 分布数组 获取 当前 数字的分布 下标
int num = getws(arr[k], i);
//根据分布数组中对应数字的 值 可直接获得下标
int c = fb[num]--;
//3.2 放到help数组中
helpArr[c-1] = arr[k];
}
//4 排序后的数组 放到 arr中
arr = helpArr;
System.out.println(arr.toString());
}
return arr;
}
private static int getMaxWs(int[] arr) {
int max = 0;
for (int i = 0; i < arr.length; i++) {
max=Math.max(arr[i],max);
}
int ws =0;
while (max!=0){
max/=10;
ws++;
}
return ws;
}
/**
* 获取 num 数字 第 a 位的数
* @param
* @return
*/
private static int getws(int num ,int a) {
//Math.pow(10, a) 意思就是10的 a 次 幂 a = 3 就等于 10*10*10 a=0 就等于0
// 1234 除 0 就得 1234 除 10 就得 123
// % 10 求余 那10进制的数除以10不就剩个位了么
return ((num / ((int) Math.pow(10, a))) % 10);
}
public static void main(String[] args) {
int[] nums = new int[]{1234,3,2,1,33,22,11,333,222,111};
nums = sort(nums);
System.out.println(nums);
}
}
别人的实现
package class08;
import java.util.Arrays;
public class Code04_RadixSort {
// only for no-negative value
public static void radixSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
public static int maxbits(int[] arr) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
max = Math.max(max, arr[i]);
}
int res = 0;
while (max != 0) {
res++;
max /= 10;
}
return res;
}
// arr[L..R]排序 , 最大值的十进制位数digit
public static void radixSort(int[] arr, int L, int R, int digit) {
final int radix = 10;
int i = 0, j = 0;
// 有多少个数准备多少个辅助空间
int[] help = new int[R - L + 1];
for (int d = 1; d <= digit; d++) { // 有多少位就进出几次
// 10个空间
// count[0] 当前位(d位)是0的数字有多少个
// count[1] 当前位(d位)是(0和1)的数字有多少个
// count[2] 当前位(d位)是(0、1和2)的数字有多少个
// count[i] 当前位(d位)是(0~i)的数字有多少个
int[] count = new int[radix]; // count[0..9]
for (i = L; i <= R; i++) {
// 103 1 3
// 209 1 9
j = getDigit(arr[i], d);
count[j]++;
}
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
for (i = R; i >= L; i--) {
j = getDigit(arr[i], d);
help[count[j] - 1] = arr[i];
count[j]--;
}
for (i = L, j = 0; i <= R; i++, j++) {
arr[i] = help[j];
}
}
}
public static int getDigit(int x, int d) {
return ((x / ((int) Math.pow(10, d - 1))) % 10);
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100000;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
radixSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
radixSort(arr);
printArray(arr);
}
}