基数排序(含Java实现)

基数排序

  1. 算法思想

    将每一个关键字的各位,依次进行稳定的计数排序

  2. 时间复杂度:

    设数组长度为n,最大数的位数为k,进制为r,

    则需要k次循环进行分配和收集,

    每一次分配需要O(n),收集需要O(n),即为O(k*n)

    (如果采用链式存储则每一次分配收集都需要O(n+r),即为O(k*(n+r))

  3. 空间复杂度:

    需要r个桶以及n个临时数组来收集,即为O(n+r)

    (如果采用链式存储则不需要临时数组,即为O(r))

  4. 稳定性: 稳定

  5. 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); // 统计错误次数
    	}
    }
    
    
原文地址:https://www.cnblogs.com/iceix/p/13832066.html