快速排序

快速排序

  本文主要讲解的是快速排序。快速排序是最快的通用内部排序算法,它由C. A. R. Hoare在1962年提出。
  快速排序采用的是分治的思想。基本原理如下:先找出一个元素(理论上可以随便找一个,但通常选取数组的第一个数)作为基准,然后对数组进行划分操作,使基准左边元素的值都不大于基准值,基准右边元素的值都不小于基准值。这样一来,作为基准的元素已经调整到其正确位置上。再不断重复上述操作,即将左右的两个子数组进行递归,如此便可将其他n-1个元素也调整到正确位置上。至此,数组已经处于前后有序的状态,排序完成。
  所以,个人认为,快速排序算法的核心其实是对数组进行的划分操作,即如何调整基准的位置,以及如何返回基准的最终位置以便进一步递归。因此下面具体讲一下这一步操作如何实现。(对于初学者而言可能会有一点点绕,但请务必弄清楚每个细节)
  具体步骤叙述大致如下:
  1)设置两个变量low,high,排序开始的时候:low=0,high=n-1;
  2)以数组中第一个元素作为基准,赋值给key,即key=a[0];
  3)从high开始由后往前开始搜索(满足low < high的条件下),即不断地执行high–,找到第一个小于key的值a[high],将a[low]赋值为a[high]并执行low++;
  4)从low开始由前往后开始搜索(满足low < high的条件下),即不断地执行low++,找到第一个大于key的值a[low],将a[high]赋值为a[low]并执行high–;
  5)重复3,4两个步骤,直到low=high,把此处赋值为key即可;
  经过上面五个步骤,至此,我们就已经成功地对数组进行了划分操作。
  如果大家还是看的一头雾水,那么下面给出一个例子。假设用户输入了如下所示的一个数组:

下标012345
数据627389

  声明变量low=0(指向第一个元素), high=5(指向最后一个元素), key=6(赋值为第一个元素的值)。
  我们要把所有比key小的数移动到key的左边,所以我们开始从右往左寻找比key=6小的数,从high开始从右往左找,不断递减变量high的值,我们找到下标3的数据比key=6小,于是把数据3移到下标为low=0的位置,把low++,完成第一次比较:

下标012345
数据327389

  此时low=1, high=3, key=6
  接着开始第二次比较,这次变成从左往右寻找比key大的数了。从low开始从左往右找,不断递增low的值,我们找到下标2的数据比key=6大,于是把数据2移到下标为high=3的位置,把high–,数据状态变成下表:

下标012345
数据327789

  此时low=2, high=2, key=6
  如果读懂了上文所说的步骤的话,就不难理解:这两次比较即为3,4两个步骤。接着,需不断重复进行上面的循环比较操作直至low=high。
  在本例中,我们进行了一次循环比较操作,就发现low和high已经“碰头”了:它们都指向了下标2。再把a[low]赋值为key。至此,我们已经完成了对数组的划分操作。得到结果如下,对于key=6,凡是其左边的数都比它小,凡是其右边的数都比它大:

下标012345
数据326789

  然后,对由key分成的两边的子数组,再分别递归进行上述的划分过程。直到不能再分组,数组排序完成。
  最后,给出快速排序的源代码如下:

#include<cstdio>
using namespace std;

inline void Rd(int& res) {
    res = 0;
    char c;
    short f = 1;
    while(c = getchar(), c < 48 && c != '-');
    do
        if(c == '-') f = -1;
        else res = (res << 3)+(res << 1)+(c ^ 48);
    while (c = getchar(), c > 47);
    res *= f;
}

const int M = 1000005;
int a[M];

void qsort(int L, int R) {
    if(L >= R) return;
    int key = a[L], low = L, high = R;
    while(low < high) {
        while(low < high && key <= a[high])
            --high;
        if(low < high)
            a[low++] = a[high];
        while(low < high && key >= a[low])
            ++low;
        if(low < high)
            a[high--] = a[low];
    }
    a[low] = key;
    qsort(L, low-1), qsort(low+1, R);
}

int main() {
    int n;
    Rd(n);
    for(int i = 0; i < n; i++)
        Rd(a[i]);
    qsort(0, n-1);
    for(int i = 0; i < n; i++)
        printf("%d%c", a[i], i==n-1?'\n':' ');
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值