Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java排序优于原语计数排序_Java_Performance_Sorting_Counting Sort - Fatal编程技术网

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

为什么Java排序优于原语计数排序,java,performance,sorting,counting-sort,Java,Performance,Sorting,Counting Sort,我正在比较Counting sort与Java native Array.sort的运行时间。从我读到的内容来看,计数排序提供了最佳、平均和最坏情况下的n+k运行时间。JavasArrays排序原语,使用双枢轴快速排序,是一种基于比较的算法,因此在平均情况下必须提供O(nLogn),在最坏情况下必须提供On2 通过测量排序一系列大小从500到100k的数组所需的时间(纳秒)来比较这两种方法时,我注意到当大小达到~70k时,计数排序的运行时间急剧增加 我的理解是,只要输入数据的范围不明显大于要排序

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

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

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

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

我的计数排序实现:

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;

    }
公共静态int[]countSort(int[]arr,int k){
/*
*这只适用于0到K的正整数。
*对于负最坏情况测试,我们使用下面的负计数排序。
* 
*步骤1:使用数组存储每个元素的频率。对于数组
*元素1到K初始化大小为K的数组。步骤2:添加
*对数组进行计数,以便每个元素存储其先前元素的总和。步骤
*3:修改后的计数数组存储元素在实际排序中的位置
*步骤5:迭代数组并将元素放置在正确的位置
*基于修改的计数数组,并将计数减少1。
*/
int[]结果=新int[arr.length];
int[]计数=新的int[k+1];
对于(int x=0;x
分辨率: 按照@Alex的建议在适当的位置运行计数排序,可以获得更好的运行时间


只是一个猜测,但是您的排序算法比Java使用的内存多得多。70k的整数是280KB。您需要两倍的空间,超过512KB。根据所使用的处理器,在(一级?)缓存中运行排序与大量缓存未命中之间可能存在差异。既然你真的不需要副本,就在适当的地方进行排序。如果你现在稍后碰壁,你就有答案了

编辑: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;
}
public static int[]countSortRefactored(int[]arr,int k){
int[]计数=新的int[k+1];
对于(int x=0;x对于(int x=0;xHey!问题是为什么会出现尖峰,还是为什么Javas排序优于自定义排序?仅供参考:注意Javas排序是高度优化的,可能使用本机系统方法。你不能用“正常”来击败它代码。我已经试过了。Java不再使用快速排序。它使用Tim排序。或者这是一个双枢轴快速排序?您在测试中使用的硬件规格是什么?嗨,这是一个2.9Ghz i7 8 GB 1600 MHz DDR3 MacBook可能相关:Hi Axel,它是一个intel i7双核,每个核有L2 256kb和L3 4MB。性能会下降吗从二级到三级的切换?是的,我就是这么想的。您提到过就地执行排序,这是如何实现的?缓存未命中的好处是:由于quicksort具有近似顺序的访问模式,它应该比countingsort经历的缓存未命中要少得多,countingsort在所有地方都进行随机访问。这可能解释了quicksort的原因rt的速度更快,尽管它执行的指令要多得多。请尝试我刚才提供的示例代码。我真的很感兴趣这有什么不同,以及它与Java的Timsort相比有什么不同。