八大排序算法

c++八大排序

目录:
- 1.计数排序
- 2.基数排序
- 3.快速排序
- 4.冒泡排序
- 5.选择排序
- 6.归并排序
- 7.堆排序
- 8.插入排序

计数排序

计数排序是一种稳定的算法,能在线性时间O(n+k)对n个数进行排序,范围【0,k】
将A数组排序时,先将小于等于Ai的数记录在C中,根据C的数值计算Ai在B的位置。

时间复杂度:o(n+k)
空间复杂度:k+n
是否稳定:稳定

代码实现:

for(int i=0;i<n;i++){
    scanf("%d",&A[i+1]);
    C[A[i+1]]++;
}
for(int i=1;i<M;i++)C[i]+=C[i-1];
for(int j=1;j<=n;j++){
    B[C[A[j]]]=A[j];
    C[A[j]]--;
}
for(int i=1;i<=n;i++)printf("%d ",B[i]);

基数排序

基数排序(gay sort)非常快,史(小C)称最快排序。但是只能排自然数。

时间复杂度:O(d(n+k)) k为基数,d为最大的位数
空间复杂度:n+r
是否稳定:稳定

代码实现:

#define N 65536
#define M 100005
int P=(1<<16)-1;
void gaysort(){
    memset(cnt,0,sizeof(cnt));
    for(int i=0;i<=N;i++)cnt[A[i]&P]++;
    for(int i=1;i<=N;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;i--)B[cnt[A[i]&P]--]=A[i];

    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)cnt[(b[i]>>16)&P]++;
    for(int i=1;i<=N;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;i--)A[cnt[(B[i]>>16)&P]--]=B[i];
}

快速排序

快速排序(quick sort)是一种比较快的原地排序但是不稳定。

平均复杂度:O(nlog(n))
最差复杂度:O(n^2)
空间复杂度:O(n)
是否稳定:不稳定

代码实现:

void Sort(int L,int R){
    if(L>R)return;
    int key=A[L];
    int a=L,b=R;
    while(a<b){
        while(a<b&&A[b]>=key)b--;
        if(a<b)A[a]=A[b];
        while(a<b&&A[a]<=key)a++;
        if(a<b)A[b]=A[a];
    }
    A[a]=key;
    if(a-1>L)Sort(L,a-1);
    if(a+1<R)Sort(a+1,R);
}

冒泡排序

冒泡排序是将大的数一个一个swap上去,是稳定的算法,但是比较慢

时间复杂度O(n^2)
空间复杂度O(n)
是否稳定:稳定

代码实现:

int* BubbleSort(int* ary, int length){
    int i, j, tmp;
    for(i=0; i<length-1; i++){
        tmp = ary[i];
        for(j=length-1; j>i; j--){
            if(tmp > ary[j]){
                swap(ary[i],ary[j]);
            }
        }
    }
    return ary;
}

选择排序

选择排序比较无脑(个人认为),每一次把最小的选出来放在最前面,就实现了排序。

时间复杂度:O(n^2)
空间复杂度:O(n)

代码实现:

for(int i=1;i<=n;i++){
        int k=i;
        for(int j=i+1;j<=n;j++)
            if(num[j]<num[k])k=j;
        if(k!=i)t=num[i];num[i]=num[k];num[k]=t;
    }

归并排序

归并排序利用了分治的思想,将一个数组切成两半,然后在排序

时间复杂度:O(nlog(n))
空间复杂度:O(n)
是否稳定:稳定

代码实现:

void Merge(int L,int R){
    if(L==R)return;
    int mid=(L+R)/2;
    Merge(L,mid); 
    Merge(mid+1,R);
    int i=L,j=mid+1,k=L;
    while(i<=mid&&j<=R){
        if(A[i]<=A[j])B[k++]=A[i++];
        else{
            B[k++]=A[j++];
            cnt+=mid-i+1;
        } 
    }
    while(i<=mid)B[k++]=A[i++];
    while(j<=R)B[k++]=A[j++];
    for(k=L;k<=R;k++)A[k]=B[k]; 
} 

堆排序:

堆排序没什么用,个人觉得用stl里面的priority_queue或是multiset都可以满足。但是这排序的想法与实现都是非常重要的

时间复杂度:O(nlog(n))
空间复杂度:O(n)
是否稳定:不稳定

代码实现:

void swap(int &a,int &b){//交换两个数
    int t=a;a=b;b=t;
}
void down(int k){
    while(2*k<=sz){
        int a=2*k;
        if(a+1<=sz&&heap[a]>heap[a+1])a++;//找较小的儿子
        if(heap[k]>heap[a])swap(heap[k],heap[a]);//交换
        else break;
        k=a;//往下走
    }
}
//初始化堆得时候,可以把n/2到1的每个元素都down下。
int heap[200005],sz;//sz记录当前堆得大小,也是最后一个元素的下标
int main(){
    int i,j,k,n;
    scanf("%d",&n);
    sz=n;
    for(i=1;i<=n;i++)
        scanf("%d",&heap[i]);
    for(i=n/2;i>=1;i--) down(i);//初始化堆
    for(i=1;i<=n;i++){
        printf("%d ",heap[1]);
        heap[1]=heap[sz--];//用最后一个元素覆盖堆顶,在删除最后一个元素
        down(1);//调整堆
    }
    return 0;
}

/*堆也可以添加元素,原理down类似,用up,把数字添加在heap[++sz]的位置上。
如果父亲节点比当前元素小,就不断向上。*/
void up(int k){
    while(k>1){
        int a=k/2;//a是父亲节点
        if(heap[a]>heap[k])swap(heap[k],heap[a]);
        else break;
        k=a;
    }
}

插入排序

插入排序说的形象点就是像打牌理牌差不多,找第一个比他大的位置,再把数字往后移。

时间复杂度:O(n^2)
空间复杂度:O(n)
是否稳定:不稳定

代码实现:

for(int i=1;i<=n;i++){
         int x=a[i];
         for(int j=i-1;j>0&&x<a[j];j--)
            a[j+1]=a[j];
        a[j+1]=x;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值