Java,Pivot Selection中的快速排序实现

时间:2016-02-17 16:11:50

标签: java quicksort

我在java中的ArrayList上实现了一个通用的quickSort,但只有当我选择pivot作为数组中最右边的项时它才有效。我已经尝试选择中间项和随机项,这两个都返回ArrayList仅部分排序。我特别想知道为什么两个注释掉quickSortRecursive中的透视选择方法导致ArrayList不能一直排序。任何帮助表示赞赏!

public static <T> void quicksort(ArrayList<T> a, Comparator<? super T> cmp){
    int left = 0;
    int right = a.size()-1;
    quickSortRecursive(left, right,a, cmp);
}

private static <T> void quickSortRecursive(int left,int right, ArrayList<T> a,  Comparator<? super T> cmp){

    if(left >= right){
        return;
    }
    T pivot = a.get(right);
    //T pivot = a.get(rand.nextInt(a.size()-1));
    //T pivot = a.get((left+right)/2);

    int partition = partition(left, right, pivot, a, cmp);
    quickSortRecursive(0, partition-1,a,cmp);
    quickSortRecursive(partition+1, right,a,cmp);

}


private static <T> int partition(int left,int right,T pivot, ArrayList <T> a,Comparator<? super T> cmp){

    int leftCursor = left-1;
    int rightCursor = right;

    while(leftCursor < rightCursor){
        while(cmp.compare(a.get(++leftCursor), pivot)<0);
        while(rightCursor > 0 && (cmp.compare(a.get(--rightCursor), pivot)>0));
        if(leftCursor >= rightCursor){
            break;
        }
        else{
            swap(leftCursor, rightCursor, a);
        }
    }
    swap(leftCursor, right, a);
    return leftCursor;
}


public static <T> void swap(int left,int right, ArrayList<T> a){
    T temp = a.get(left);
    a.set(left, a.get(right));
    a.set(right, temp);
}

2 个答案:

答案 0 :(得分:0)

所以你几乎到了那里但是有些事情我看错了这段代码:

  • <T>通常用于声明具有未知类型的函数或创建通用函数,此处不必使用它。您可以简单地使用您选择的任何类型的数组,即int[] data
  • ,而不是arrayList
  • Pivot是在数据范围内任意选择的索引,尽管使用(left + right) / 2它常见的类型很可能是int
  • 您有两种方法quickSortRecursivepartition。但是,这些属于一个函数,因为您需要为要排序的数据的每个子集计算轴。此方法不需要返回类型,因此只需在方法声明中使用void

成功将数据划分为子集后,您需要选择一个数据透视表,将该数据透视与该子集中的最后一项交换。

然后,您需要遍历数据子集并将每个数据项与数据透视值进行比较(数据子集位于数据子集的末尾,因为我们刚刚交换它)。如果数据项小于pivot索引处的值,则 交换物品。

在交换了所有项目之后,有必要将数据放在枢轴索引处,将其与最后一个要排序的项目交换。

只有才能递归调用其余数据上的函数:

递归调用函数时:

quickSortRecursive(0, partition-1,a,cmp);
quickSortRecursive(partition+1, right,a,cmp);

你应该向左传递而不是0进入函数,因为传递0将导致总是从数据的最左侧进行排序。

希望这有帮助。

答案 1 :(得分:0)

--rightCursor首先递减变量然后使用它(已经递减)。

所以,自right=a.size()-1;以来,最右边的元素将被忽略(除了最后比较的枢轴元素)。