Java 为什么我的快速排序这么慢?

Java 为什么我的快速排序这么慢?,java,sorting,complexity-theory,quicksort,Java,Sorting,Complexity Theory,Quicksort,作为面试准备的一部分,我正在练习写排序算法,我想知道是否有人能帮我找出为什么这种快速排序不是很快?它似乎具有正确的运行时复杂性,但它比我的合并排序慢一个常数因子,大约为2。如果有任何评论能够改进我的代码,而这些评论不一定能回答这个问题,我也将不胜感激 非常感谢你的帮助!如果我犯了任何礼仪错误,请不要犹豫,告诉我。这是我的第一个问题 private class QuickSort implements Sort { @Override public int[] s

作为面试准备的一部分,我正在练习写排序算法,我想知道是否有人能帮我找出为什么这种快速排序不是很快?它似乎具有正确的运行时复杂性,但它比我的合并排序慢一个常数因子,大约为2。如果有任何评论能够改进我的代码,而这些评论不一定能回答这个问题,我也将不胜感激

非常感谢你的帮助!如果我犯了任何礼仪错误,请不要犹豫,告诉我。这是我的第一个问题

private class QuickSort implements Sort {

        @Override
        public int[] sortItems(int[] ts) {
            List<Integer> toSort = new ArrayList<Integer>();
            for (int i : ts) {
                toSort.add(i);
            }
            toSort = partition(toSort);
            int[] ret = new int[ts.length];
            for (int i = 0; i < toSort.size(); i++) {
                ret[i] = toSort.get(i);
            }
            return ret;
        }

        private List<Integer> partition(List<Integer> toSort) {
            if (toSort.size() <= 1)
                return toSort;
            int pivotIndex = myRandom.nextInt(toSort.size());
            Integer pivot = toSort.get(pivotIndex);
            toSort.remove(pivotIndex);
            List<Integer> left = new ArrayList<Integer>();
            List<Integer> right = new ArrayList<Integer>();
            for (int i : toSort) {
                if (i > pivot)
                    right.add(i);
                else
                    left.add(i);
            }
            left = partition(left);
            right = partition(right);
            left.add(pivot);
            left.addAll(right);
            return left;
        }

}
私有类快速排序实现排序{
@凌驾
公共int[]sortItems(int[]ts){
List-toSort=new-ArrayList();
用于(int i:ts){
加入(i);
}
toSort=分区(toSort);
int[]ret=新的int[ts.length];
对于(int i=0;i
非常感谢所有帮忙的人

这是我为子孙后代改进的课程:

private class QuickSort implements Sort {

        @Override
        public int[] sortItems(int[] ts) {
            int[] ret = ts.clone();
            partition(ret,0,ret.length);
            return ret;
        }

        private void partition(int[] toSort,int start,int end) {
            if(end-start<1) return;
            int pivotIndex = start+myRandom.nextInt(end-start);
            int pivot = toSort[pivotIndex];
            int curSorted = start;
            swap(toSort,pivotIndex,start);
            for(int j = start+1; j < end; j++) {
                if(toSort[j]<pivot) {
                    if(j!=curSorted+1) 
                        swap(toSort,curSorted,curSorted+1);
                    swap(toSort,j,curSorted++);
                }
            }
            // Now pivot is at curSorted
            partition(toSort,start,curSorted);
            partition(toSort,curSorted+1,end);
        }
    }
私有类快速排序实现排序{
@凌驾
公共int[]sortItems(int[]ts){
int[]ret=ts.clone();
分区(ret,0,ret.length);
返回ret;
}
私有无效分区(int[]到排序,int开始,int结束){

如果(结束-开始)快速排序的最大优点之一是它可以作为就地算法实现。不要创建新列表,而是就地对元素进行排序。

除了不重用列表外,您还可以在每个步骤中在整数和整数之间进行转换:

        for (int i : toSort) {  // converts from Integer to int
            if (i > pivot)
                right.add(i);  // converts from int to Integer
            else
                left.add(i);   // converts from int to Integer
        }
请注意,从int到Integer的转换通常需要创建一个新对象


最后,random.nextInt()可能是一个非常重要的操作。如果toSort超过一定大小,则最好只选择一个随机轴,否则使用更简单的pivor选择策略(测量它!).

还有,看看你的输入是否没有接近排序!@Saurabh:真的没有理由这么做。如果你总是选择最左边的元素作为轴心,快速排序只会对排序后的输入显示出反常的二次性能。对于随机选择的或三个轴心的中值,这不是问题(在OP的代码中,轴是随机选择的)。@James:即使你说的是准确的,随机选择轴也有输入(取决于随机选择)因此,尽管Saurabh的评论并不完全准确,但评论的动机仍然值得考虑:病理数据/角落案例等@Muron:king。对于某些输入,某些快速排序实现具有二次时间复杂度这一事实只是alg的已知事实算法。这不是真正的病态。但是,当对已经排序的输入进行排序需要二次时间时,这是病态的,因为这是不合理的。对于大多数用例,数据很可能已经排序或大部分排序。随机轴选择需要二次时间对序列进行排序的可能性非常大功率(几乎不重要)也就是说,如果我没记错的话,这是Bob Sedgewick用来证明为什么中位数为3的轴选择在大多数情况下比随机轴选择更可取的几个原因之一。尽管如此,但当数组的数字完全随机时,快速排序实际上是最快的,而合并排序则是CA顺序不重要。我建议你看看集合中的快速排序代码。它相当快速有效。或者你可以直接使用它。+1作为标题讽刺:)