一个快排模版及其边界分析

221 阅读1分钟

先把代码贴上来

#include <iostream>

using namespace std;

const int N = 1000010;

int q[N];

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

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

int main()
{
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    quick_sort(q, 0, n - 1);

    for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);

    return 0;
}

注意,一下边界分析基于此模板,不同的写法有不同的边界情况,最好选一个自己喜欢的模板,然后直接背下来

情况一ij已经到达的相邻的位置

此时执行下列代码,ij的位置将会相换

while (i < j)
    {
        do i++; while (q[i] < x);
        do j--; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }

image.png 此时,不管选取(l, j) (j + 1, r)还是(l, i - 1) (i, r)都是可是正确划分的。 情况二ij重合且终止了 此时上述描述依旧成立

但是

如果考虑更加极端的情况,例如一个只有两个元素的数组[1, 2],此时l + r >> 1必然选取第一个元素,即 1 ,即选取的pivot(代码中的x)为1。 执行下列代码:

while (i < j)
    {
        do i++; while (q[i] < x);
        do j--; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }

i停在数组第一个位置,j也停在数组第一个位置,此时如果选取(l, i - 1) (i, r),那就越界啦。