0785-快速排序

题目描述

关系

内容

785. 快速排序 - AcWing题库

问题分析

思路分析

执行流程设计

总结

代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;
int n;
int a[N];

void quick_sort(int l, int r) {
    if (l >= r) return;
    
    int x = a[(l + r) >> 1], i = l - 1, j = r + 1;
    while (i < j) {
        do i++; while (a[i] < x);
        do j--; while (a[j] > x);
        if (i < j) swap(a[i], a[j]);
    }
    
    quick_sort(l, j);
    quick_sort(j + 1, r);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    
    quick_sort(0, n - 1);
    for (int i = 0; i < n; i++) cout << a[i] << " ";
    return 0;
}

循环结束时,i >= j

正常情况下,按照循环不变式,我们应该会觉得结果已经显然了

因为i >= jq[l..i] <= x, q[j..r] >= x

所以按照j来划分的话,q[l..j] <= x, q[j+1..r] >= x是显然的

可是,最后一轮循环有点特殊,因为最后一轮循环的if语句一定不会执行

因为最后一轮循环一定满足 i >= j,不然不会跳出while循环的,所以if语句一定不执行

正确分析:

由于最后一轮的if语句一定不执行

所以,只能保证:

q[l..i-1] <= x, q[i] >= x

q[j+1..r] >= x, q[j] <= x

i >= j
q[l..i-1] <= xi >= j(i-1 >= j-1)q[j] <= x 可以得到 q[l..j] <= x

又因为q[j+1..r] >= x
所以,q[l..j] <= x,q[j+1..r] >= x,问题得证

总结:只有最后一轮循环结束时,循环不变式不成立,其余的循环都是成立的
但最终要求的问题还是解决了

注意:循环结束时要记得检查是否存在数组越界/无限划分的情况

所以还需要证明 j 最终的取值范围是[l..r-1](即不存在n划分成0和n的无限划分情况),分析过程在分析5