考虑如下的数组,
int[] a = {100, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 16};
考虑将中间元素作为支点。
pivot = 10
标准快速排序算法如下所示
public void quickSort(int[] a, int low, int high) {
if (a == null || a.length == 0)
return;
if (low >= high)
return;
int pivotIndex = partition( a, low, high );
quickSort(a, low, pivotIndex-1);
quickSort(a, pivotIndex, high);
}
public int partition ( int[] a, int low, int high )
{
// pick the pivot
int middle = low + (high - low) / 2;
int pivot = a[middle];
while (low <= high) {
while (a[low] < pivot) {
low++;
}
while (a[high] > pivot) {
high--;
}
if (low <= high) {
swap( a, low, high );
low++;
high--;
}
}
return low;
}
完成while循环的一次迭代后(绕10旋转),数组如下所示
high low
10 1 2 3 4 5 100 11 12 13 14 15 16
如您所见,pivot元素位于索引0处,该位置不是10的正确位置。
我的问题是,如何修改上述算法,以便在每次迭代结束时,枢轴元素处于正确的位置,我们继续递归左右两半,而不考虑枢轴
答案 0 :(得分:0)
如果目标是在开始时将枢轴值放在其(他们的)正确位置,则代码可以对阵列进行单次扫描,检查小于,等于或大于数值的值,例如生成三个计数:ltpivot =#elements&lt; pivot value,eqpivot =#elements == pivot,gtpivot =#elements&gt;枢轴值。 (通过扫描只需要生成两个计数,第三个计数将是(高+ 1 - 低 - (计数中的2个))。然后所有的数据透视值应移动到索引位置低+ ltpivot到低+ ltpivot + eqpivot - 1.这可以通过另一个传递将枢轴值交换到位来完成。然后可以进行第三次传递以将小于或大于枢轴的元素交换到枢轴的左侧或右侧。
问题是这种方法比标准快速排序慢,需要对阵列进行3次扫描,而不是标准快速排序的单次扫描。标准快速排序只会正确放置一个枢轴元素,留下任何其他元素==枢轴分散,但在典型情况下,这不是问题。 (标准快速排序的最坏情况之一是所有值都相同)。