码迷,mamicode.com
首页 > 编程语言 > 详细

快速排序

时间:2018-02-14 13:25:00      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:turn   main   长度   ace   body   部分   swa   down   注意   

快速排序

我居然现在还不会快排。

第一种写法:

// luogu-judger-enable-o2
#include <cstdio>
using namespace std;

const int maxn=1e5+5;
int n, a[maxn];

void swap(int &a, int &b){
    int tmp=a; a=b; b=tmp; }

void sort(int l, int r){ // 代表[l,r)
    //两哨兵太难写了,一哨兵大X好
    if (l+1>=r) return;
    int std=a[l], now=l;
    for (int i=l+1; i<r; ++i) //比std小的都排到左端
        if (a[i]<std) swap(a[i], a[++now]); //能取等号?
    swap(a[l], a[now]);
    sort(l, now); sort(now+1, r); //now+1,避免死循环
}

int main(){
    scanf("%d", &n);
    for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
    sort(1, n+1);
    for (int i=1; i<=n; ++i) printf("%d ", a[i]);
    return 0;
}

这种单哨兵的方法,和双哨兵且有一个哨兵带等号的方法一样,都有一个致命缺陷——当序列中数字全部相同时,时间退化到n^2。这就是交这个程序到洛谷上tle的原因。于是我找到了写法二——

#include <cstdio>
using namespace std;

const int maxn=1e5+5;
int n, a[maxn];

void swap(int &a, int &b){
    int tmp=a; a=b; b=tmp; }

void sort(int l, int r){ //左闭右开区间
    if (l+1>=r) return;
    int std=a[(l+r)>>1];
    int i=l, j=r-1;
    while (i<=j){ //避免撞车使i和j没有到预定位置,加上等号
        //注意两个while不能带等号,不然i或j可能一冲到底
        //,造成区间大小不变,陷入死循环
        while (a[i]<std) ++i;
        while (a[j]>std) --j;
        //可能i和j都冲过头了,要避免这种情况下交换
        if (i<=j){ //同理避免撞车,加上等号
            swap(a[i], a[j]);
            //若来到了与基准值相等的区域,就需要用蛮力推进了
            ++i; --j;
        }
    }
    sort(l, j+1); sort(i, r);
}

int main(){
    scanf("%d", &n);
    for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
    sort(1, n+1);
    for (int i=1; i<=n; ++i) printf("%d ", a[i]);
    return 0;
}

大部分注意点但都写在代码中了,我来解释一下。首先,用左闭右开区间,是因为看了刘汝佳的书,书中说这种区间表示法更好。while中不能带等号,不然要么死循环,要么超时。由于区间的划分时按照i和j来决定的,所以i必须正好在基准值右侧,j必须正好在基准值左侧,才能保证在长度为二的区间中不出现循环情况。因此,i<j的判定要加上等号,这样j一定小于i。哎,快排真是最难写的算法。

快速排序

标签:turn   main   长度   ace   body   部分   swa   down   注意   

原文地址:https://www.cnblogs.com/MyNameIsPc/p/8448165.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!