zoukankan      html  css  js  c++  java
  • 洛谷 P1177 【模板】快速排序(排序算法整理)

    题目描述

    利用快速排序算法将读入的N个数从小到大排序后输出。

    快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。(C++选手请不要试图使用STL,虽然你可以使用sort一遍过,但是你并没有掌握快速排序算法的精髓。)

    输入输出格式

    输入格式:

     

    输入文件sort.in的第1行为一个正整数N,第2行包含N个空格隔开的正整数a[i],为你需要进行排序的数,数据保证了A[i]不超过1000000000。

     

    输出格式:

     

    输出文件sort.out将给定的N个数从小到大输出,数之间空格隔开,行末换行且无空格。

     

    输入输出样例

    输入样例#1: 复制
    5
    4 2 4 5 1
    输出样例#1: 复制
    1 2 4 4 5

    说明

    对于20%的数据,有N≤1000;

    对于100%的数据,有N≤100000。

    分类 ------------ 内部比较排序
    数据结构 --------- 数组
    最差时间复杂度 ---- 每次选取的基准都是最大(或最小)的元素,导致每次只划分出了一个分区,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2)
    最优时间复杂度 ---- 每次选取的基准都是中位数,这样每次都均匀的划分出两个分区,只需要logn次划分就能结束递归,时间复杂度为O(nlogn)
    平均时间复杂度 ---- O(nlogn)
    所需辅助空间 ------ 主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度,一般为O(logn),最差为O(n)       
    稳定性 ---------- 不稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n;
    int num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        sort(num+1,num+1+n);
        for(int i=1;i<=n;i++)
            cout<<num[i]<<" ";
    }
    sort的快速排序

    分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(n^2) 最优时间复杂度 ---- 如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,可以把最优时间复杂度降低到O(n) 平均时间复杂度 ---- O(n^2) 所需辅助空间 ------ O(1) 稳定性 ------------ 稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        for(int j=1;j<=n;j++)
            for(int i=1;i<=n-j;i++)
                if(num[i]>num[i+1])
                    swap(num[i],num[i+1]);
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    冒泡排序 n^2

    分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(n^2) 最优时间复杂度 ---- 如果序列在一开始已经大部分排序过的话,会接近O(n) 平均时间复杂度 ---- O(n^2) 所需辅助空间 ------ O(1)
    稳定性 ------------ 稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN];
    int l,r;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        l=1;r=n;
        while(l<r){
            for(int i=l;i<r;i++)
                if(num[i]>num[i+1])
                    swap(num[i],num[i+1]);
            r--;
            for(int i=r;i>l;i--)
                if(num[i-1]>num[i])
                    swap(num[i],num[i-1]);
            l++;
        }
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    改良版的冒泡排序(鸡尾酒排序)

    分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(n^2) 最优时间复杂度 ---- O(n^2) 平均时间复杂度 ---- O(n^2) 所需辅助空间 ------ O(1) 稳定性 ------------ 不稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        for(int i=1;i<=n;i++){
            int minn=i;
            for(int j=i+1;j<=n;j++)
                if(num[j]<num[minn])
                    minn=j;
            if(minn!=i)    swap(num[i],num[minn]);
        }
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    选择排序

    分类 ------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- 最坏情况为输入序列是降序排列的,此时时间复杂度O(n^2) 最优时间复杂度 ---- 最好情况为输入序列是升序排列的,此时时间复杂度O(n) 平均时间复杂度 ---- O(n^2) 所需辅助空间 ------ O(1) 稳定性 ------------ 稳定
    插入
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        for(int i=2;i<=n;i++){
            int get=num[i];
            int j=i-1;
            while(j>=0&&num[j]>get){
                num[j+1]=num[j];
                j--;
            }
            num[j+1]=get;
        }
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    排序

    分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(n^2) 最优时间复杂度 ---- O(nlogn) 平均时间复杂度 ---- O(n^2)
    所需辅助空间 ------ O(1) 稳定性 ------------ 稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        for(int i=2;i<=n;i++){
            int get=num[i];
            int l=0,r=i-1;
            while(l<=r){
                int mid=(l+r)/2;
                if(num[mid]>get)    r=mid-1;
                else l=mid+1;
            }
            for(int j=i-1;j>=l;j--)
                num[j+1]=num[j];
            num[l]=get;
        }
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    二分的插入排序

    分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- O(nlogn) 最优时间复杂度 ---- O(nlogn) 平均时间复杂度 ---- O(nlogn) 所需辅助空间 ------ O(n) 稳定性 ------------ 稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN],tmp[MAXN];
    void up(int l,int mid,int r){
        int len=r-l+1;
        int i=l,j=mid+1,tot=0;
        while(i<=mid&&j<=r){
            tmp[++tot]=num[i]<num[j]?num[i++]:num[j++];
        }
        while(i<=mid)    tmp[++tot]=num[i++];
        while(j<=r)    tmp[++tot]=num[j++];
        for(int k=1;k<=tot;k++)
            num[l++]=tmp[k];
    }
    void work1(int l,int r){
        if(l==r)    return ;
        int mid=(l+r)/2;
        work1(l,mid);
        work1(mid+1,r);
        up(l,mid,r);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        work1(1,n);//递归版本 
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    递归版的归并排序
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,num[MAXN],tmp[MAXN];
    void up(int l,int mid,int r){
        int len=r-l+1;
        int i=l,j=mid+1,tot=0;
        while(i<=mid&&j<=r){
            tmp[++tot]=num[i]<num[j]?num[i++]:num[j++];
        }
        while(i<=mid)    tmp[++tot]=num[i++];
        while(j<=r)    tmp[++tot]=num[j++];
        for(int k=1;k<=tot;k++)
            num[l++]=tmp[k];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        int l,r,mid;
        for(int i=1;i<=n;i*=2){
            l=1;
            while(l+i<=n){
                mid=l+i-1;
                r=mid+i<=n?mid+i:n;
                up(l,mid,r);
                l=r+1;
            }
        }
        for(int i=1;i<=n;i++)    cout<<num[i]<<" ";
    }
    非递归版本的归并排序

    分类 ------------ 内部非比较排序 数据结构 --------- 数组 最差时间复杂度 ---- O(n + k) 最优时间复杂度 ---- O(n + k) 平均时间复杂度 ---- O(n + k) 所需辅助空间 ------ O(n + k) 稳定性 ----------- 稳定
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int tmp[MAXN];
    int n,maxn,num[MAXN];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
            tmp[num[i]]++;
            maxn=max(maxn,num[i]);
        }    
        for(int i=1;i<=maxn;i++)
            while(tmp[i]){
                cout<<i<<" ";
                tmp[i]--;
            }
    }
    桶排序

    其他的就没有什么用了吧,等以后有时间再整理。

    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    hdu 2639 Bone Collector II
    文件打包bundle
    iOS UITextField垂直居中
    Mac删除废纸篓中的单一文件和文件夹
    Swift 初见
    关于 Swift
    NSString和NSDate的转换
    iOS开发之iOS7设置状态栏字体颜色
    在当前界面中隐藏状态栏
    适合所有测试人员读的书籍
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7793243.html
Copyright © 2011-2022 走看看