有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

性能为什么Java排序优于原语计数排序

我将计数排序的运行时间与Java本机数组进行比较。分类从我读到的内容来看,计数排序提供了最佳、平均和最坏情况下的n+k运行时间。JavasArrays排序原语,使用双枢轴快速排序,是一种基于比较的算法,因此在平均情况下必须提供O(nLogn),在最坏情况下必须提供On2

通过测量排序一系列大小从500到100k的数组所需的时间(纳秒)来比较这两种方法时,我注意到当大小达到~70k时,计数排序的运行时间急剧增加

我的理解是,只要输入数据的范围不明显大于要排序的元素数,计数排序就是有效的 数组是由0到99之间的随机数组成的,因此k总是比n小得多

当n增加时,计数排序会如此突然地退化,有什么特别的原因吗

Running time in nanoseconds (y) vs Array size (x)

我的计数排序实现:

public static int[] countSort(int[] arr, int k) {
        /*
         * This will only work on positive integers 0 to K.
         * For negative  worst case testing we use the negative count sort below.
         * 
         * Step 1: Use an array to store the frequency of each element. For array
         * elements 1 to K initialize an array with size K. Step 2: Add elements of
         * count array so each element stores summation of its previous elements. Step
         * 3: The modified count array stores the position of elements in actual sorted
         * array. Step 5: Iterate over array and position elements in correct position
         * based on modified count array and reduce count by 1.
         */

        int[] result = new int[arr.length];
        int[] count = new int[k + 1];
        for (int x = 0; x < arr.length; x++) {
            count[arr[x]]++;
        }

        /*
         * Store count of each element in the count array Count[y] holds the number of
         * values of y in the array 'arr'
         */

        for (int y = 1; y <= k; y++) {
            count[y] += count[y - 1];
        }

        /*
         * Change count[i] so that count[i] now contains actual Position of this element
         * in result array
         */

        for (int i = arr.length - 1; i >= 0; i--) {
            result[count[arr[i]] - 1] = arr[i];
            count[arr[i]]--;
        }

        System.out.println("COUNTSORT SORTED ARRAY = " + Arrays.toString(result));
        return result;

    }

分辨率: 按照@Alex的建议在适当的位置运行计数排序,可以获得更好的运行时间

Run time of modified in-place count sort vs Java primitive sort


共 (1) 个答案

  1. # 1 楼答案

    只是猜测一下,但是你的排序算法使用的内存比Java的多得多。70k的整数是280KB。你需要两倍的空间,超过512KB。根据所用处理器的不同,这可能会影响在(L1?)中运行排序缓存和大量缓存未命中。既然你真的不需要副本,那就在适当的地方进行分类。如果你现在稍后碰壁,你就知道答案了

    编辑:280KB

    Edit2:昨天很晚了,所以现在是现场版本。请注意,它会修改输入数组

    public static int[] countSortRefactored(int[] arr, int k) {
        int[] count = new int[k + 1];
        for (int x = 0; x < arr.length; x++) {
            count[arr[x]]++;
        }
    
        int idx=0;
        for (int x=0; x<=k; x++) {
            Arrays.fill(arr, idx, idx+=count[x], x);
        }
    
        System.out.println("COUNTSORT SORTED ARRAY = " + Arrays.toString(arr));
        return arr;
    }