洛谷 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]--;
        }
}
桶排序

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

 

 

posted @ 2017-11-06 15:06  一蓑烟雨任生平  阅读(509)  评论(0编辑  收藏  举报