开发者

Why is my quick sort so slow?

I am practicing writing sorting algorithms as part of some interview preparation, and I am wondering if anybody can help me spot why this quick sort is not very fast? It appears to have the correct runtime complexity, but it is slower than my merge sort by a constant factor of about 2. I would also appreciate any comments that would improve my code that don't necessarily answer the question.

Thanks a lot for your help! Please don't hesitate to let me know if I have made any etiquette mistakes. This is my first question here.

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;
     开发者_JAVA百科   }

        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;
        }

}

Thanks a ton, everybody who helped!

This is my much improved class for posterity:

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);
        }
    }


One of the biggest advantages of Quicksort is that it can be implemented as an in-place algorithm. Don't create new lists, sort the elements in-place instead.


In addition to not reusing lists, you convert between Integer and int in each step:

        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
        }

Note that conversion from int to Integer in general requires a new object to be created.

And finally random.nextInt() might be a non-trivial operation. Perhaps it would be better to only select a random pivot if the toSort exceeds a certain size and use a simpler pivor selection strategy otherwise (Measure it!).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜