我最近重新访问了quicksort。我曾经通过从列表中选择最后一项或第一项来进行数据透视。但是另一个我碰到了这个片段,其中的片段是从中间拾取的。我知道枢轴的计算方式只会影响算法的性能。但我只是无法理解这种分区算法。
我想我了解分区算法的问题是,我认为它应该使结果数组像所有小于枢轴的项目都移到左侧,而所有大于枢轴的项目都移到左侧正确的。但是,这种分区算法并不总是能够实现这一目标。
private static void quickSort (int[] array, int left, int right) {
int index = partition(array, left, right);
//Sort left half
if (left < index - 1)
quickSort(array, left, index - 1);
//Sort right half
if (index < right)
quickSort(array, index , right);
}
private static int partition (int array[], int left, int right) {
int pivot = array[(left + right) / 2]; //Pick pivot point
while (left <= right) {
//Find element on left that should be on right
while (array[left] < pivot)
left++;
//Find element on right that should be on left
while (array[right] > pivot)
right--;
//Swap elements and move left and right indices
if (left <= right) {
int temp = array[left];
array[left] = array[right];
array[right] = temp;
left++;
right--;
}
}
return left;
}
如果我给分区算法一个数组[1,0,-1,3,5,10,-5]
,则枢轴将为3
,但是在分区之后,数组为[ 1, 0, -1, -5, 5, 10, 3 ]
。我只是无法理解它,因为它看起来好像分区没有做任何有意义的事情。它没有将数组分成两半。
答案 0 :(得分:1)
代码是Hoare分区方案的一种变体,其中每个分区步骤导致所有元素<枢轴位于所有元素的左侧>枢轴,但是元素==枢轴(包括枢轴本身)可以终止于左侧的任何位置或右分区,具体取决于数据模式。这就是为什么递归调用使用index-1和index的原因,因为返回的索引与枢轴不对应,因此不能将其排除在递归调用之外。
在示例情况下,在第一个分区步骤中,由于array [{0,1,2}] <枢轴,所以将左移至3,由于array [{6}]不是>,因此右未更改>枢纽,导致swap(array [3],array [6]),设定array [3] = -5和array [6] = 3(枢纽)。
答案 1 :(得分:0)
枢轴将移至右侧,而不会进行后续排序。左右指针已适当调整。从三个部分重新考虑该数组:左,右和枢轴。而不是
[ 1, 0, -1, -5, 5, 10, 3 ]
你有
[ 1, 0, -1, -5], [5, 10], [ 3 ]
left
中的所有内容都小于枢轴; right
中的所有内容都更大。