浏览器标题切换
浏览器标题切换end

计蒜客T1746 - 快速排序 - 快排模板题 - 递归写法

时间复杂度

平均情况: \(Ο(nlogn)\)

最坏状况下则需要 \(Ο(n^2)\) 次比较

AC代码(以左边为基准)

#include<iostream>
#include<string>
#include<cmath>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;

int a[100010],n;

void quicksort(int L, int R)
{
    if(L>=R) return;
    int i=L,j=R; // a[L]中存的就是基准数
    while(i!=j)
    {
        //要先从右边开始找(不能交换顺序)
        // (最后交换基准时换过去的数要保证比基准小,因为基准选取数组第一个数,在小数堆中)
        while(a[j]>=a[L]&&i<j) j--;   // 大的放右
        while(a[i]<=a[L]&&i<j) i++; //再找右边的  // 小的放左
        if(i<j) swap(a[i],a[j]);
    }
    swap(a[L],a[i]); // 将基准数归位
    quicksort(L,i-1); // 递归继续处理左边的
    quicksort(i+1,R); // 递归继续处理右边的
}

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

优化过的快排AC代码

这个是以最右边为基准点。

优化:基准点随机选择。

#include<iostream>
#include<string>
#include<cmath>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;

int a[100010],n;

void quicksort(int L,int R)
{
    if(L>=R) return;

    int p=rand()%(R-L+1)+L;  //p就是[L,R)范围内随机生成的基准数下标 (随机下标)
    // 也可以p=L+(R-L)/2; // 或p=(L+R)/2(中间元素下标)

    swap(a[p],a[R]);// 把最后一个数a[R]变成基准数
    int i=L,j=R,x=a[R]; // x是基准数  最右边那个元素定为基准数
    while(i<j)
    {
        while(a[i]<=x&&i<j) i++; // 小的放左
        while(a[j]>=x&&i<j) j--;   // 大的放右
        if(i<j) swap(a[i],a[j]);
    }
    //结束while会出一个新的基准数a[j],j是基准数下标
    //***这个时候i肯定>=j 所以if(i>j)这个条件写不写都ok
    swap(a[j],a[R]); // 将基准数归位
    quicksort(L,i-1); // 递归继续处理左边的
    quicksort(i+1,R); // 递归继续处理右边的
}

int main()
{
    srand(time(0)); //srand(time(NULL));
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    quicksort(0,n-1);
    for(int i=0;i<n;i++)
        printf("%d ",a[i]);
    cout<<endl;
    return 0;
}

优化过的快排代码注意问题

  1. 为什么j不等于R-1,要等于R?

    • 把这两组数据分别代进去走一遍:1 2 或 2 1
  2. 进入while的时候为什么要先让i往右走再让j往左走,而不是先让j先往左i再往右?

    • 把这组数据代入 1 7 8 5 我们会发现,如果先让j先走的话,j和i之后会同时走到数字1这个位置,当while出去的时候,会把1和5进行交换,这样子小的数字就跑到基准数的位置上去了,从而造成错误。
posted @ 2021-03-10 19:09  抓水母的派大星  阅读(79)  评论(0编辑  收藏  举报