void quick_sort(vector<int>& nums, int l, int r) {
if (l >= r) return;
int mid = nums[(l + r) >> 1];
int i = l - 1, j = r + 1;
while (i < j) {
do ++i; while (nums[i] < mid);
// 这里一定不可以 =
// 因为存在一种情况,我们比较的 target 刚刚好是一个区间的最大值或者最小值
// 不加 = 号的话,i 和 j 都总是会入侵到对方的区间
// 加了之后,会存在
// 如果target刚好是最大值,i入侵不到
// 如果target刚好是最大值,j入侵不到
// 一般情况下:扫描完一次之后
// i = j + 1 分别入侵了 大于target 和小于target 的区域
// 或者是 i == j 都入侵了 target
do --j; while (nums[j] > mid);
if (i < j) {
swap(nums[i], nums[j]);
}
}
cout << i << " " << nums[i] << " "<< j << " " << nums[j] << " " << mid << endl;
quick_sort(nums, l,j);
quick_sort(nums, j + 1, r);
// 这里:
// 可以是 j 和 j + 1
// 也可以是 i - 1 和 i
// 因为在最后,i 是向左进入了他不应该进入的地区:nums[i] >= mid
// j 是向左进入了 他不该进入的地区, 所以是: nums[j] <= mid
// 所以 j 需要被左侧包含进去,i需要被右侧包含进去
/*所有的可能:
按照顺序排好了:
find 6
0 1 2 3 4
5 8 9
i j
j i
没按照顺序排好了:
find 8
0 1 2 3 4
5 9 8
i j
i j
5 8 9
i j
j i*/
}
void quick_sort1(vector<int>& nums, int l, int r) {
if (l >= r) return;
int temp = nums[l];
int i = l, j = r;
while (i < j) {
while (i < j && nums[j] > temp) --j;
if (i < j) nums[i++] = nums[j];
while (i < j && nums[i] < temp) ++i;
if (i < j) nums[j--] = nums[i];
}
nums[j] = temp;
cout << i << " " << nums[i] << " " << j << " " << nums[j] << " " << temp << endl;
quick_sort1(nums, l, j);
quick_sort1(nums, j + 1, r);
// 这个和第一个就不同
// 这个快排的终止条件一定是 i == j
// 而且是把 目标值放在了 i == j的位置上
// 这个也能像第一种快排方法一样理解
// 当快排序完成时:中间会有一条分界线 左边<= target 右边>= target
// 但是第二种快排,当i和j有一个入侵到对方时,另一个就不会入侵了,最多走到i == j的位置
// 而且这时把 target 放到了这个位置
}