NOIP之路

【语法篇】15、快速排序

2017-02-28  本文已影响15人  沧海无雨

排序问题,是生活中非常常见的问题,关于排序问题,足以专门开辟一个专栏来写,包括最简单的选择排序啦、冒泡法啦、桶排法啦等等。排序方法有很多种,不同的排序方法有各自不同的特点。在这里介绍一种排序——快速排序。它的时间复杂度是nlogn,几乎是所有排序方法中最快的一种了。

一、快排的思想

快排基本思路是(以从小到大排序):(1)选择一个“基准”;(2)将比“基准”小的数放在左边,比“基准”大的数放在右边;(3)继续递归调用该函数,直到排序中只剩下1个数。
其中在第(2)步中,为了节省时间,往往是在左边找到“大的数”(大于基准),右边找到“小的数”(小于基准),然后交换两者的数值。直到左右两边相遇,即完成了关于“基准”的一次排序(即实现比基准小的数放左边,比基准大的数放右边)。
值得注意的是,在选择“基准”上,有多种不同的方式,比较常见的选择方式是:选第一个数和选中间的数这两种。下面将分别用这两种方式来实现。

二、快排的代码实现

1、选中间值为“基准”

#include <iostream>
using namespace std;
const int maxn=10000;
int a[maxn+10]; //定义全局变量

void qsort(int left, int right){//两个参数是数组的左下标和右下标 
    int i=left, j=right;
    int key=a[(i+j)/2]; //基准,中间值 
    while(i<=j){
        while(a[i]<key )//不能越过基准,所以不能有等号 
            i++;
        while(a[j]>key)
            j--;
        if(i<=j){
            int t=a[i];
            a[i]=a[j];
            a[j]=t;
            i++;
            j--;
        }
    }
    if(i<right) //递归调用右边 
        qsort(i,right);
    if(left<j)  //递归调用左边 
        qsort(left,j);
}

int main(){
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    qsort(1,n); //快排函数,调用数组,从a[1]到a[n]进行排序
    for(int i=1; i<=n; i++) //输出快排后的数 
        cout<<a[i]<<" ";  
    return 0;   
}

2、选第一个数为“基准”

#include <iostream>
using namespace std;
const int maxn=10000;
int a[maxn+10]; //定义全局变量

void qsort(int left, int right){//两个参数是数组的左下标和右下标 
    if(left>right) //至少要有1个数以上才需要排序。即right-left+1>=1,化简为right>=left,反过来,结束排序的条件为它的非命题。 
        return ;
    int i=left, j=right;
    int key=a[left];//选第一个数为基准
    while(i<j){
        while(a[j]>=key && i<j)
            j--;
        while(a[i]<=key && i<j)
            i++;
        if(i<j){
            int t=a[i];
            a[i]=a[j];
            a[j]=t;
        }
    }
    a[left]=a[i];
    a[i]=key;
    qsort(i+1,right); //右边
    qsort(left,i-1);  //左边 
}

int main(){
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    qsort(1,n); //快排函数,调用数组,从a[1]到a[n]进行排序
    for(int i=1; i<=n; i++) //输出快排后的数 
        cout<<a[i]<<" ";  
    return 0;   
}

三、快排练习

1、思考:选择第一个数为“基准”时,为何要从右边开始出发?
2、按照从大到小的顺序,用快排的方式来实现。

上一篇 下一篇

猜你喜欢

热点阅读