快速排序

关于快速排序, 网上有各种教程, 就不细说.

思路就是:
找到一个基准数, 然后把小于这个数的数它放在左边, 把大于它的数放在它右边. 然后分治地解决左边和右边的排序.

一般基准有左边第一个数, 中间数, 随机某个数. 在不同的问题下, 选定不同的基准数实际时间复杂度可能会有极大差别, 理论上, 推荐随机的基准数.

实现快速排序的具体方式也有很多种, 但是基本的思路就是上面介绍的.

洛谷的快速排序模板题

AC代码是以中间数为基准数, 而之前的以左边第一个数为基准数的代码都只通过了60%的样例.

下面是代码:

#include <iostream>
using namespace std;

void quickSort(int *a, int l, int r)
{
    int x = l, y = r, mid = a[(l + r) >> 1];
    do {
        while(a[x] < mid) x++;
        while(a[y] > mid) y--;
        if(x <= y) {
            swap(a[x], a[y]);
            x++, y--;
        }
    } while(x <= y);
    if(x < r) quickSort(a, x, r);
    if(y > l) quickSort(a, l, y);
}

int main()
{
    int n;
    cin >> n;
    int *a = new int[n+1];
    for(int i = 0; i < n; ++i) {
        cin >> a[i]; 
    }
    quickSort(a, 0, n - 1);
    for(int i = 0; i < n; ++i) {
        cout << a[i] << ' ';
    }
    cout << endl;
}

样例:

10
6 1 2 7 9 3 4 5 10 8

7
4 7 3 1 4 8 6

7
9 4 7 3 1 4 8 6 

其实快排的代码算是挺短的, 但是在实际的过程中出现了很多难以预料的错误.
有的程序出不来, 有的没有排序排错了.

需要注意的是, 代码中有很多while循环, 对它们的功能要有很清晰的理解. 还有很多类似<, <= 这类的情况, 也要非常注意. 这些地方都非常容易出错.

以下是以左边第一个数为基准的情况

//以最左边为基准数 
#include <iostream>
#include <algorithm>
using namespace std;

void quickSort(int *a, int left, int right)
{
    if(right < left) return;
    int key = a[left], l = left, r = right;
    while(l < r) {
        while(a[r] >= key && l < r) r--;
        while(a[l] <= key && l < r) l++;
        if(l < r) swap(a[l], a[r]);
    }
    swap(a[left], a[l]);
    quickSort(a, left, l - 1);
    quickSort(a, l + 1, right);
}

int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    cin >> n;
    int *a = new int [n+1];
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    quickSort(a, 0, n - 1);
    for(int i = 0; i < n; ++i) {
        cout << a[i] << ' ';
    }
}

总之, 孰能生巧. 对于我这种蒟蒻来说, 要轻松的写好快排, 还是要多加练习, 让手把快排背下来.

刚才六分钟手打了一个快排, 零调试, 零bug(偷笑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值