手写桶排序-基数排序

限制:非负数,能表达成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);

	}

}

猜你喜欢

转载自blog.csdn.net/u010191034/article/details/121045204
今日推荐