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

Java 快速排序。如何选择轴心元素?,java,algorithm,language-agnostic,quicksort,Java,Algorithm,Language Agnostic,Quicksort,我读过关于快速排序算法的书,不知道如何选择pivot元素。从教程中,我得到了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) {

我读过关于快速排序算法的书,不知道如何选择pivot元素。从教程中,我得到了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);
}
public void快速排序(int[]A,int left,int right){
int pivot=A[left+(right-left)/2];
int i=左;
int j=右;
而(我){
j--;
}
如果(iLeft=最小值
右=最大值
你如何得到中间值?(最大值-最小值)/2

基本上,它搜索数组的中间作为轴心点


由于数组不是从0开始的,而且最小值不是一个常数,所以将最小值添加到结果中,这就是当前数组的中间部分。

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

感谢@:
您可以简单地编写
(左+右)/2

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

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

在这个特定的例子中,教程选择的是在被排序的中间的元素的枢轴,但是可能没有特别的理由这样做。


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

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


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

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

( left + right ) / 2
可能由于溢出而导致错误


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

用base
left
删除中间索引为什么不正确?因为这可能不正确。运行几个示例(手动或在调试器中运行)看看原因。@OliCharlesworth你能解释一下为什么不正确吗?@MyTitle阅读banarun的回答可能不正确总是选择最后一个元素会导致已经排序的数组性能糟糕…这就是为什么我说选择取决于接收数组的结构…是的,我的错,忘记添加最小值了。中间我s真的是(max-min)/2,但是你添加了最小值,因为最小值不是0,可能会改变。谢谢你在别人误解之前通知我我的错误。
left+(right-left)/2
=
2*left/2+(right-left)/2
=
(left+right-left)/2
@Dukeling哇!!有趣的谢谢:),我想在我的答案中加上。@Dukeling(左+右)/2和left+(右/左)/2不一样(如果它们是整数).left+right可能会导致整数溢出。@banarun是的,我不经常对超过1073 741 824个元素的数组进行排序。@Dukeling:您可能有兴趣知道这是Java的
binarySearch
多年来的一个bug:。