我读到了关于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]
答案 0 :(得分:11)
考虑left=6, right=10
,然后(right-left)/2
是2.您选择的元素不在您的子数组范围内?
您可以选择6到10之间的任何元素作为快速排序。但是如果您选择第一个或最后一个元素并且如果数组已排序,那么您的算法可能会转到O(n ^ 2)运行时间。所以选择中间元素总是更好。
答案 1 :(得分:5)
假设left=3
和right=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]
的最后一个元素,只是为了避免算术错误。