基数排序
-
算法思想:
将每一个关键字的各位,依次进行稳定的计数排序
-
时间复杂度:
设数组长度为n,最大数的位数为k,进制为r,
则需要k次循环进行分配和收集,
每一次分配需要O(n),收集需要O(n),即为O(k*n)
(如果采用链式存储则每一次分配收集都需要O(n+r),即为O(k*(n+r))
-
空间复杂度:
需要r个桶以及n个临时数组来收集,即为O(n+r)
(如果采用链式存储则不需要临时数组,即为O(r))
-
稳定性: 稳定
-
Java代码实现(LSD最低位优先,升序,包含测试)
import java.util.Arrays; import java.util.Random; public class RadixSort { public static void main(String[] args) { checkBatch(1000, 20, 100, true); } /** * 基数排序 * @param arr */ public static void radixSort(int[] arr) { if (arr.length <= 1) // 极端情况处理 return; int max = getMax(arr); // 获取最大值 for (int base = 1; max / base > 0; base *= 10) { // 以最大元素的位数为分配次数 int[] bucket = new int[10]; int[] tmp = new int[arr.length]; for (int i = 0; i < arr.length; i++) { // 分配,初始化bucket int p = arr[i] / base % 10; // 获得当前位的值 bucket[p]++; } for (int i = 1; i < 10; i++) { // 得到累加后的bucket,决定该算法稳定的关键所在 bucket[i] += bucket[i - 1]; } for (int i = arr.length - 1; i >= 0; i--) { // 收集 int p = arr[i] / base % 10; tmp[bucket[p] - 1] = arr[i]; bucket[p]--; } for (int i = 0; i < arr.length; i++) { // 替换 arr[i] = tmp[i]; } } } /** * 获取数组中的最大元素 * @param arr * @return */ private static int getMax(int[] arr) { int max = arr[0]; for (int i = 1; i < arr.length; i++) { if (max < arr[i]) max = arr[i]; } return max; } /** * 打印数组的所有元素 * @param arr */ private static void showArray(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } /** * 对比两个数组的所有元素是否一致 * @param arr0 * @param arr1 * @return: 是否一致 */ private static boolean check(int[] arr0, int[] arr1) { for (int i = 0; i < arr1.length; i++) { if (arr0[i] != arr1[i]) return false; } return true; } /** * 单次测试 * @param maxSize: 测试数组的最大长度 * @param maxNum: 测试数组的元素最大值 * @param show: 是否展示数组 * @return: 是否错误 */ private static boolean checkOnce(int maxSize, int maxNum, boolean show) { boolean bool = true; Random rd = new Random(); int size = rd.nextInt(maxSize + 1); //0 ~ maxSize int[] arr0 = new int[size]; int[] arr1 = new int[size]; for (int i = 0; i < arr0.length; i++) { arr0[i] = rd.nextInt(maxNum + 1); // 0 ~ maxNum arr1[i] = arr0[i]; } if (show) showArray(arr0); radixSort(arr0); // 基数排序 Arrays.sort(arr1); // 自带排序 bool = check(arr0, arr1); if (show) { showArray(arr0); if (!bool) { System.out.println("error!"); } } return bool; } /** * 批量测试 * @param times: 测试次数 * @param maxSize: 测试数组的最大长度 * @param maxNum: 测试数组的元素最大值 * @param show: 是否展示数组 */ private static void checkBatch(int times, int maxSize, int maxNum, boolean show) { int error = 0; for (int i = 0; i < times; i++) { if (!checkOnce(maxSize, maxNum, show)) error++; } System.out.println("error_sum: " + error); // 统计错误次数 } }