快速排序。如何选择枢轴元素?

时间:2013-07-03 07:30:06

标签: java algorithm language-agnostic quicksort

我读到了关于quicksort算法的内容,我不明白如何选择枢轴元素。从教程我得到quciksort的示例代码:

public void quicksort(int[] A, int left, int right) {
    int pivot = A[left + (right - left) / 2];
    int i = left;
    int j = right;
    while (i <= j) {
        while (A[i] < pivot) {
            i++;
        }
        while (A[j] > pivot) {
            j--;
        }
        if (i <= j) {
            exchange(i, j);
            i++;
            j--;
        }
    }

    if(left < j)
        quicksort(A,left,j);
    if(i < right)
        quicksort(A,i,right);
}

但是为什么我们选择使用此A[left + (right - left) / 2];

进行数据透视

为什么不A[(right - left) / 2]

6 个答案:

答案 0 :(得分:11)

考虑left=6, right=10,然后(right-left)/2是2.您选择的元素不在您的子数组范围内?

您可以选择6到10之间的任何元素作为快速排序。但是如果您选择第一个或最后一个元素并且如果数组已排序,那么您的算法可能会转到O(n ^ 2)运行时间。所以选择中间元素总是更好。

答案 1 :(得分:5)

假设left=3right=9然后right-left/2 = 3不是中间的,而是6 = left + (right - left) / 2。 (只是添加了基值left)。

感谢@ Dukeling
你可以简单地写(left + right) / 2

    left + (right-left)/2 
=>  2*left/2 + (right-left)/2    //multiply (left * 2/2)
=>  (2*left + right-left)/2 
=>  (left + right)/2

答案 2 :(得分:1)

左=最小 对=最大 你怎么得到中间的? (最大 - 最小)/ 2

基本上它会搜索数组的中间位置作为支点。

由于数组不是从0开始,并且最小值不是常数,所以在结果中添加最小值 - 这是当前数组的中间值。

答案 3 :(得分:1)

可能你应该理解这个函数的意思是:将数组A从索引左边快速排序到索引右边。什么是A [(右 - 左)/ 2]?可能它不是数组A的元素。

答案 4 :(得分:1)

( left + right ) / 2

可能会因溢出而导致错误。

假设left = 1&amp; right = INT_MAX然后( left + right ) / 2 = 0,这是不正确的。这是由于溢出造成的,为避免这种情况,我们选择left + (right - left) / 2。在数学上,两个表达式都是正确的选择中间元素。

答案 5 :(得分:0)

实际上,枢轴元素的选择是快速排序最重要的部分之一。最佳选择通常取决于您接收的数组的结构,通常很难找到适合每个数组的数据透视位置。

在这个特定的例子中,教程选择了作为枢轴的元素在被调整的段的中间,但可能没有特别的理由这样做。

我,我通常选择片段pivot = A[right]的最后一个元素,只是为了避免算术错误。