排序算法(稳定)

来源:互联网 发布:代挂乐最新源码 编辑:程序博客网 时间:2024/05/18 00:30

稳定排序


1.计数排序
2.基数排序
3.插入排序
4.冒泡排序
5.归并排序


计数排序

int A[M];void sort() {    int n,x;    scanf("%d",&n);    FOR(i,1,n){        scanf("%d",&x);        A[x]++;//统计每个数值出现的次数    }    FOR(i,0,M-1)while(A[i]--) printf("%d ",i);}

最简单也是复杂度最低的排序算法
计数排序的对象一般范围比较小
而且必须是非负整数
复杂度:O(n+m) n为元素个数,m为数值范围


基数排序

const int P=(1<<16)-1;const int M=1<<16; int A[M],B[M],cnt[M+5];void sort(){    FOR(i,1,n)cnt[A[i]&P]++;    FOR(i,1,M)cnt[i]+=cnt[i-1];    DOR(i,n,1)B[cnt[A[i]&P]--]=A[i];    memset(cnt,0,sizeof(cnt));    FOR(i,1,n)cnt[(B[i]>>16)&P]++;    FOR(i,1,M)cnt[i]+=cnt[i-1];    DOR(i,n,1)A[cnt[(B[i]>>16)&P]--]=B[i];}

计数排序的升级版,范围更广
复杂度(n*m),m为最长数位长度


插入排序

int A[M];void sort(){    FOR(i,1,n){        int j,x=A[i];        for(j=i-1;j>0&&x<a[j];j--)            A[j+1]=A[j];//比x大的数往后挪         A[j+1]=x;//插入x     }}

复杂度平均为O(n^2),最好O(n)


冒泡排序

int A[M];void sort(){    FOR(i,1,n){        int f=1;        //第i次冒泡时,判断[1,n-i]内每个数与它后面的数         FOR(j,1,n-i)            if(A[j]>A[j+1]){                swap(A[j],A[j+1]);                f=0;//发生了冒泡             }        if(f)break;//如果没有发生冒泡,说明已经有序,可结束。     }}

复杂度O(n^2),最好情况下O(n)
冒泡排序发生的交换次数等于逆序对数


归并排序

int A[M],B[M];void Merge(int L,int R){    if(L==R)return;//序列长度为1,叶子节点    int mid=L+R>>1;    Merge(L,mid); //排左边     Merge(mid+1,R);//排右边     int i=L,j=mid+1,k=L;//合并[L,mid]和[mid+1,R]这两个有序序列     //先把合并结果放到B数组的[L,R]     while(i<=mid&&j<=R){        if(A[i]<=A[j])B[k++]=A[i++];        else{            B[k++]=A[j++];            cnt+=mid-i+1;//A[j]比左边[i,mid]这个区间的数都小,产生逆序对         }     }    while(i<=mid)B[k++]=A[i++];    while(j<=R)B[k++]=A[j++];    FOR(i,L,R)A[i]=B[i];//赋值回A数组 } 

将待排序的序列分开再合并,可以利用递归来实现
合并有序序列的复杂度可以做到O(a+b),a和b表示两个有序序列的长度
共logn层,每层向上合并的复杂度是O(n),总的复杂度是O(nlogn)
归并排序的复杂度是很稳的nlogn,不会被卡
归并排序也可以用来求逆序对的数量

原创粉丝点击