1.确定分界点(x):
分界点可以为左侧端点q[l];中间点q[l+r/2];右侧q[r],令它为x
2.定义两个指针i,j
i从指向q[l]开始向后移动,如果q[i]<x,就继续向后移动,否则,停止。
j从指向去q[r]开始向前移动,如果q[j]>x,就继续向前移动,否则,停止。
然后,交换q[i],q[j],使得比x小的数在左边,比x大的数在右边,分治。
当两指针即将相遇时,停止,此时q[i]的左边全部小于x,q[j]的右边全部大于x,
3.递归处理左右两边
将分治后的左右两个数组再进行分治
void sort_quick(vector<int>& nums, int l, int r) {
if (l >= r) {
return;
}
int x = nums[l];//或者x = q[l + r >> 1];//向上取整,相当于nums[l]
int i = l - 1;
int j = r + 1;
while(i < j) {
do i++; while(nums[i] < x);
do j--; while(nums[j] > x);
if (i < j) {
swap(nums[i],nums[j]);
}
}
sort_quick(nums, l, j);//注意,这里右端点要取j,由于int x = nums[l],不然最后剩下两个数时会死循环。分析见下:
sort_quick(nums, j + 1, r);
}
由于while(i < j)循环结束时,i>=j,i=j时没问题,当i>j时,且只剩下两个元素,由于x = nums[l],会一直死循环。
或者
void sort_quick(vector<int>& nums, int l, int r) {
if (l >= r) {
return;
}
int x = nums[r];//或者x = q[l + r + 1 >> 1];//向上取整,相当于nums[l]
int i = l - 1;
int j = r + 1;
while(i < j) {
do i++; while(nums[i] < x);
do j--; while(nums[j] > x);
if (i < j) {
swap(nums[i],nums[j]);
}
}
sort_quick(nums, l, i - 1);//注意,这里右端点要取i - 1,由于int x = nums[r],不然最后剩下两个数时会死循环。分析见下:
sort_quick(nums, i, r);
}