我本质上是从UCBerkeley快速排序视频中复制代码的,但似乎几乎是成对排序的。我不确定这是怎么回事。
我已经多次浏览每行,看不到出了什么问题。一切对我来说都很有意义。
static <E extends Comparable<? super E>>
void quicksort(E[] A, int low, int high) {
if (low < high) {
int pivotIndex = (low + high) / 2;
E pivot = A[pivotIndex];
// move pivot to end
A[pivotIndex] = A[high];
A[high] = pivot;
int i = low - 1;
int j = high;
do {
do {
i++;
} while (A[i].compareTo(pivot) < 0);
do {
j--;
} while ((A[i].compareTo(pivot)) > 0 && (j > low));
if (i < j) {
E swap = A[i];
A[i] = A[j];
A[j] = swap;
}
} while (i < j);
// i is now the first spot in the right partition (where we will put pivot)
// now put pivot back where it belongs
A[high] = A[i];
A[i] = pivot;
quicksort(A, low, i - 1); // sort left partition
quicksort(A, i + 1, high);
}
}
我期望[2、3、5、6、10、101、200、300],但得到了[3、5、2、6、10、101、200、300]
答案 0 :(得分:1)
当第二个内部循环中的比较应该使用A [j]时,则使用A [i]:
} while ((A[j].compareTo(pivot)) > 0 && (j > low)); // A[j] not A[i]
这种类型的快速排序的另一种变体是不将枢轴与A [high]交换,并且通过将枢轴保留在中间,代码无需在第二个内部循环中检查j> low,这有点快。使用此变体还需要进行其他更改:将j初始化为high + 1,并且两个递归调用应为quicksort(A,low,j)和quicksort(A,j + 1,high)。请注意,等于枢轴的值(包括枢轴本身)可能会在任一分区中终止,因为等于枢轴的值会被交换。
基元(int)的示例代码,该代码在较小或相等的部分上使用递归,然后对较大的部分进行迭代,以避免在最坏的情况下发生堆栈溢出。可以将其转换为使用通用对象E。
public static void qsort(int[] a, int lo, int hi)
{
while(lo < hi){
int md = lo+(hi-lo)/2;
int ll = lo-1;
int hh = hi+1;
int p = a[md];
int t;
while(true){
while(a[++ll] < p);
while(a[--hh] > p);
if(ll >= hh)
break;
t = a[ll];
a[ll] = a[hh];
a[hh] = t;
}
ll = hh++;
if((ll - lo) <= (hi - hh)){
qsort(a, lo, ll);
lo = hh;
} else {
qsort(a, hh, hi);
hi = ll;
}
}
}