【模板】排序算法

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;
        }
    }
}
posted @ 2022-11-06 19:17  caijianhong  阅读(20)  评论(0编辑  收藏  举报