快速排序的思路是:在数组中找到一个元素,保证这个个元素的左边都小于这个元素,右边大于这个元素,这个操作称为切分,那个元素称为“切分元素”。
每次切分数组,保证“切分元素“”右边的元素总是大于“切分元素”,“切分元素”左边的元素总是小于“切分元素”。那么,这个“切分元素”的最终位置便确定了,在其左右的两个子数组的切分过程中,它不再参与。(但是不能保证切分元素在数组的中央位置)
public static void quickSort(int[] a) {
sort(a, 0, a.length - 1);
}
public static void sort(int[] a, int lo, int hi) {
if (lo >= hi) return;
int mid = partition(a, lo, hi); //切分函数,确定了mid的最终位置
sort(a, lo, mid - 1); //递归切分左子数组
sort(a, mid + 1, hi); //递归切分右子数组
}
public static void partition(int[] a, int lo, int hi) {
int i = lo, j = hi + 1;
int v = a[lo]; //将第一个元素定为切分元素
while (true) {
while (a[i++] < v) if (i == hi) break; //i最终会定位到hi或右子数组的最左位置
while (a[j--] > v) if (j == lo) break; //j最终会定位到lo或左子数组的最右位置
if (i >= j) break;
exch(a, i, j);
}
exch(a, lo, j); //将切分元素与小于它的左子数组的最右交换位置
return j;
}
另外,如果使用辅助数组很容易实现切分,但将切分后的数组复制回去的开销也许会得不偿失,大大降低排序的速度。所以请原地切分。
参考《算法》