• 各类排序算法


    各类排序算法

    简单介绍各类排序算法,并给出相对应的模板
    练习oj P1177 【模板】快速排序

    冒泡排序

    时间复杂度:O(n2)
    类似水中冒气泡的原理
    相邻两个气泡之间比较,大的气泡往上冒

    //冒泡排序 O(n2)
    void bubble_sort(int l,int r,int a[]){
        for(int i=l;i<r;++i){
            bool f=0;
            for(int j=l;j<r+l-i;++j){
                if(a[j]>a[j+1]){ //相邻气泡比较,大的往上冒
                    swap(a[j],a[j+1]);
                    f=1;
                }
            }
            if(f==0) break; //没有发生交换,说明已经排序好
        }
    }
    

    插入排序

    时间复杂度:O(n2)
    类似打扑克牌时,依次整理发到手里的牌
    拿到一张牌,与手里已有的牌进行比较,找到合适位置,移出来一张牌的空位后插入

    优化:因为手里的牌已经是有序的,可以通过二分查找,更快的找到插入位置

    //插入排序 O(n2)
    void insert_sort(int l,int r,int a[]){
        int t;
        for(int i=l;i<=r;++i){
            t=a[i];
            //当前插入第i张牌
            int l1=l,r1=i,mid; //r=n(0~n-1)
            while(l1<r1){ //二分查找
                mid=(l1+r1)/2;
                if(a[i]>a[mid]) l1=mid+1; //> l=m+1
                else r1=mid; //r=m
            } //移出来一个牌位
            for(int j=i-1;j>=l1;--j) a[j+1]=a[j];
            a[l1]=t; //插入
        }
    }
    

    选择排序

    时间复杂度:O(n2)
    依次找最小的元素,逐个替换到前面

    //选择排序 O(n2)
    void select_sort(int l,int r,int a[]){
        for(int i=l;i<r;++i){
            int k=i;
            for(int j=i+1;j<=r;++j){
                if(a[j]<a[k]) k=j; //找到最小的元素,交换到首部
            }
            if(k!=i) swap(a[i],a[k]);
        }
    }
    

    桶排序

    时间复杂度:O(n+m)
    简言之就是利用数组进行排序
    时间很美观,但空间是个大问题

    //桶排序 O(n+m) 空间容易MLE
    //需要一个超大的数组
    #define inf 123456
    int cnt[123456]={0};
    void bucket_sort(int l,int r,int a[]){
        int ma=0,mi=inf; //记录最大最小值 优化排序时间
        for(int i=l;i<=r;++i){
            ++cnt[a[i]];
            ma=max(ma,a[i]);
            mi=min(mi,a[i]);
        }
        int p=l;
        for(int i=mi;i<=ma;++i)
            while(cnt[i]--)
                a[p++]=i;
    }
    

    希尔排序

    时间复杂度:O(n1.3-n2)
    插入排序的改进版
    通过设置一个间隔,对相同间隔的数进行插入排序,从而实现大步位移(插入排序每次只能移动一位)。最后的间隔必须等于1,来确保整体有序
    间隔序列有多种,这里gap=N/2

    //希尔排序 O(n1.3-n2)
    void shell_sort(int l,int r,int a[]){
        for(int gap=(r+1-l)/2;gap>0;gap/=2) //间隔序列N/2 最后间隔为1
            for(int i=l+gap;i<=r;++i) //间隔gap个元素有序
                for(int j=i;j>=l+gap&&a[j]<a[j-gap];j-=gap) //间隔gap插入排序
                    swap(a[j],a[j-gap]); //大步位移
    }
    

    归并排序

    时间复杂度:O(nlogn)
    分而治之的策略
    画图理解起来很快,这里推荐 图解排序算法(四)之归并排序

    //归并排序 O(nlogn) 分而治之
    int tmp[123456]={0};
    void merge(int l,int m,int r,int a[]){
        int i=l; //左序列指针
        int j=m+1; //右序列指针
        int p=0;
        while(i<=m&&j<=r){ //两个指针依次比较
            if(a[i]<a[j]) tmp[p++]=a[i++];
            else tmp[p++]=a[j++];
        }
        while(i<=m) tmp[p++]=a[i++]; //剩余元素填充
        while(j<=r) tmp[p++]=a[j++];
        p=0;
        while(l<=r) a[l++]=tmp[p++];
    }
    void merge_sort(int l,int r,int a[]){
        if(l>=r) return;
        int mid=(l+r)/2;
        merge_sort(l,mid,a);
        merge_sort(mid+1,r,a);
        merge(l,mid,r,a);
    }
    

    堆排序

    利用堆(优先队列)来排序
    这里偷懒就不手写堆了,直接用STL

    //堆排序 O(nlogn)
    void heap_sort(int l,int r,int a[]){
        priority_queue<int,vector<int>,greater<int>> q; //小顶堆
        for(int i=l;i<=r;++i) q.push(a[i]);
        int p=l;
        while(!q.empty()){
            a[p++]=q.top();
            q.pop();
        }
    }
    

    快速排序

    时间复杂度:O(nlogn)
    类似归并的分治思想,从待排的元素中找到一个基准数,将比它大的放在右边,小的放在左边

    //快速排序 O(nlogn)
    void quick_sort(int l,int r,int a[]){
        if(l>=r) return;
        int i=l,j=r; //左右两个指针
        srand(time(0));
        int pivot=rand()%(l-r)+l;
        swap(a[pivot],a[l]);
        int tmp=a[l]; //待排的第一个元素作为基准数(随机基准数不容易tle)
        while(i!=j){ //从两边扫描,直到两个指针相遇
            while(j>i&&a[j]>=tmp) --j; //从右到左找到第一个比基准数小的元素
            a[i]=a[j]; //a[i]与a[j]交换
            while(i<j&&a[i]<=tmp) ++i;
            a[j]=a[i];
        }
        a[i]=tmp; //基准数放到中间
        quick_sort(l,i-1,a); //对基准数左边的元素排序
        quick_sort(j+1,r,a);
    }
    
  • 相关阅读:
    TP5.1 分页CSS样式(转载)
    简单的layui二级联动
    关于layui部分表单不显示的问题(Select, checkBox)
    MySQL 开启远程访问权限 | 宝塔系统
    tp5.1 本地正常, 线上route.php不起作用的问题
    cocos自动图集
    微信小程序video
    nuxt https
    接口数据加密
    node里读取命令行参数
  • 原文地址:https://www.cnblogs.com/lidasu/p/10968065.html
Copyright © 2020-2023  润新知