洛谷 P1177 【模板】快速排序(排序算法整理)
题目描述
利用快速排序算法将读入的N个数从小到大排序后输出。
快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。(C++选手请不要试图使用STL,虽然你可以使用sort一遍过,但是你并没有掌握快速排序算法的精髓。)
输入输出格式
输入格式:
输入文件sort.in的第1行为一个正整数N,第2行包含N个空格隔开的正整数a[i],为你需要进行排序的数,数据保证了A[i]不超过1000000000。
输出格式:
输出文件sort.out将给定的N个数从小到大输出,数之间空格隔开,行末换行且无空格。
输入输出样例
说明
对于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]<<" "; }
分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- 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]<<" "; }
分类 -------------- 内部比较排序 数据结构 ---------- 数组 最差时间复杂度 ---- 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]--; } }
其他的就没有什么用了吧,等以后有时间再整理。
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。