• 计蒜客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进行交换,这样子小的数字就跑到基准数的位置上去了,从而造成错误。
  • 相关阅读:
    SwiftUI_2_共享绑定
    iOS_知识点_动画&绘图
    excle表格数据列前批量添加数据
    异步编程模式学习
    这不是一篇技术文档!
    lowcode
    java中如何针对系统灵活变换分割符?
    linux安装nginx
    序列化与反序列化
    Linux安装nginx star
  • 原文地址:https://www.cnblogs.com/OFSHK/p/14513639.html
Copyright © 2020-2023  润新知