【模板】排序算法
posted on 2021-08-27 19:17:02 | under 模板 | source
万恶之源:初赛完善程序
一些定义:
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5,maxv=1e5;
时间复杂度
记 \(n\) 为元素个数,\(m\) 为元素值域。
排序方法 | 平均 | 最坏 | 最优 | 空间 | 是否稳定 | 是否比较 |
---|---|---|---|---|---|---|
插入排序 | \(O(n^2)\) | \(O(n^2)\) | \(O(n)\) | \(O(1)\) | \(\tt\color{green}Yes\) | \(\tt\color{green}Yes\) |
冒泡排序 | \(O(n^2)\) | \(O(n^2)\) | \(O(n)\) | \(O(1)\) | \(\tt\color{green}Yes\) | \(\tt\color{green}Yes\) |
选择排序 | \(O(n^2)\) | \(O(n^2)\) | \(O(n^2)\) | \(O(1)\) | \(\tt\color{red}No\) | \(\tt\color{green}Yes\) |
桶排序 | \(O(n+m)\) | \(O(n+m)\) | \(O(n+m)\) | \(O(m)\) | \(\tt\color{green}Yes\) | \(\tt\color{red}No\) |
计数排序 | \(O(n+m)\) | \(O(n+m)\) | \(O(n+m)\) | \(O(n+m)\) | \(\tt\color{green}Yes\) | \(\tt\color{red}No\) |
基数排序 | \(O(\frac{nm}{base})\) | \(O(\frac{nm}{base})\) | \(O(\frac{nm}{base})\) | \(O(n+m)\) | \(\tt\color{green}Yes\) | \(\tt\color{red}No\) |
快速排序 | \(O(n\log n)\) | \(O(n^2)\) | \(O(n\log n)\) | \(O(n)\)(系统栈) | \(\tt\color{red}No\) | \(\tt\color{green}Yes\) |
归并排序 | \(O(n\log n)\) | \(O(n\log n)\) | \(O(n\log n)\) | \(O(n)\) | \(\tt\color{green}Yes\) | \(\tt\color{green}Yes\) |
堆排序 | \(O(n\log n)\) | \(O(n\log n)\) | \(O(n\log n)\) | \(O(1)\) | \(\tt\color{red}No\) | \(\tt\color{green}Yes\) |
(注:这个表可能不靠谱。)
插入排序
void insert_sort(int a[],int l,int n){
for(int i=2;i<=n;i++){
int j;
for(j=i-1;j>=1;j--){
if(a[j]<a[i]) break;
}
if(j!=i-1){
int tmp=a[i];
for(int k=i-1;k>j;k--) a[k+1]=a[k];
a[j+1]=tmp;
}
}
}
冒泡排序
小 trick:冒泡排序交换次数 = 逆序对对数。
void bubble_sort(int a[],int l,int n){
for(int i=1;i<=n;i++){
bool flag=0;
for(int j=1;j<=n-i;j++){
if(a[j]>a[j+1]) swap(a[j],a[j+1]),flag=1;
}
if(!flag) break;
}
}
选择排序
void select_sort(int a[],int l,int n){
for(int i=1;i<=n;i++){
int k=i;
for(int j=i+1;j<=n;j++){
if(a[k]>a[j]) k=j;
}
swap(a[i],a[k]);
}
}
桶排序
int b[maxv+10];
void bucket_sort(int a[],int l,int n){
memset(b,0,sizeof b);
for(int i=1;i<=n;i++) b[a[i]]++;
int cnt=0;
for(int i=1;i<=maxv;i++) while(b[i]--) a[++cnt]=i;
}
计数排序
int b[maxv+10];
int tmp[maxn+10];
void count_sort(int a[],int l,int n){
memset(b,0,sizeof b);
for(int i=1;i<=n;i++) b[a[i]]++;
for(int i=1;i<=maxv;i++) b[i]+=b[i-1];
for(int i=n;i>=1;i--) tmp[b[a[i]]--]=a[i];
for(int i=1;i<=n;i++) a[i]=tmp[i];
}
基数排序
int b[maxv+10];
int tmp[maxn+10];
void radix_sort(int a[],int l,int n){
const int q=8,z=(1<<q)-1;
for(int e=0;e<sizeof(int)*8;e+=q){
memset(b,0,sizeof b);
for(int i=1;i<=n;i++) b[a[i]>>e&z]++;
for(int i=0;i<=z;i++) b[i]+=b[i-1];
for(int i=n;i>=1;i--) tmp[b[a[i]>>e&z]--]=a[i];
for(int i=1;i<=n;i++) a[i]=tmp[i];
}
}
快速排序
void quick_sort(int a[],int l,int r){
if(l>=r) return ;
int i=l,j=r,k=a[(l+r)/2];
do{
while(a[i]<k) i++;
while(a[j]>k) j--;
if(i<=j) swap(a[i++],a[j--]);
}while(i<=j);
quick_sort(a,l,j),quick_sort(a,i,r);
}
归并排序
小 trick:归并排序可以求逆序对对数。
int tmp[maxn+10];
void merge_sort(int a[],int l,int r){
if(l>=r) return ;
int mid=(l+r)/2;
merge_sort(a,l,mid),merge_sort(a,mid+1,r);
int i=l,n1=mid,j=mid+1,n2=r,cnt=l;
while(i<=n1&&j<=n2){
if(a[i]<=a[j]) tmp[cnt++]=a[i++];
else tmp[cnt++]=a[j++];
}
while(i<=n1) tmp[cnt++]=a[i++];
while(j<=n2) tmp[cnt++]=a[j++];
for(int k=l;k<=r;k++) a[k]=tmp[k];
}
堆排序
关于 \(O(n)\) 建堆:它不考。
void heap_sort(int a[],int l,int n){
for(int i=1;i<=n;i++){
int s=i,p=s/2;
while(p>=1&&a[s]>a[p]){
swap(a[s],a[p]);
s=p,p=s/2;
}
}
for(int i=n;i>=1;i--){
swap(a[1],a[i]);
int p=1,l=2,r=3,k;
while(k=p,l<i&&a[l]>a[k]&&(k=l),r<i&&a[r]>a[k]&&(k=r),k!=p){
swap(a[p],a[k]);
p=k,l=p*2,r=l+1;
}
}
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/16863471.html