关于各种常用排序的介绍

(声明:方便起见,本文都说的是从小到大排)

1.选择排序

原理:先选一个最小的替换第一个,再选一个最小的替换第二个......

时间复杂度O(n^2)

参考代码:

for (int i=1;i<=n;i++){
    int Min=i;
    for (int j=i+1;j<=n;j++)
        if (a[j]<a[Min]) Min=j;//找最小
    if (Min!=i) swap(a[Min],a[i]);//交换
}

 

2.冒泡排序

原理:每一次把一个数跟后一个数比较,如果前一个数大于后一个数那就把前一个数向后移

比方说:

5 4 2 1

我先比较5和4

然后把5往后移

然后就变成了

4 5 2 1

接下来依次是

4 2 5 1

4 2 1 5

2 4 1 5

2 1 4 5

1 2 4 5

时间复杂度O(n^2)

参考代码:

for (int i=1;i<=n;i++){
    for (int j=2;j<=n-i+1;j++)
        if (a[j-1]>a[j]) swap(a[j-1],a[j]);
}

 

3.桶排序

原理:先开一个足够大的数组,表示等于数组下表的数有多少个,然后只需要顺序处理一遍就可以知道数字的顺序

时间复杂度:O(n+m)

当然这个有比较大的弊端,就是当我读入的a[i]

参考代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=105;
int n,Min,a[MAXN],tot,cnt[MAXN];

int main(){
    cin>>n;tot=0;
    for (int i=1;i<=n;i++) cin>>a[i],cnt[a[i]]++;//cnt就是桶
    //其实上面已经排完了  下面是处理的过程
    for (int i=1;i<=MAXN-1;i++)
        while (cnt[i]--) a[++tot]=i;
    for (int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

 

4.归并排序

原理:别问,问就是先分分分分分分再合合合合合合

时间复杂度O(nlog2(n))

用一张图来表示一下(借的百度的一张图)

参考代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=105;
int n,Min,a[MAXN],tot,b[MAXN];

void b_sort(int l,int r){//归并排序核心部分
    if (l>=r) return ;
    if (l+1==r){
        if (a[l]>a[r]) swap(a[l],a[r]);
    }//如果递归到最底下一层就交换
    int mid=(l+r)>>1;
    b_sort(l,mid);
    b_sort(mid+1,r);//先把整个区间[l,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++];
    }//然后把两半数组按从小到大的顺序合并起来
    while (i<=mid) b[k++]=a[i++];
    while (j<=r) b[k++]=a[j++];//这个b数组是用来暂时存a数组的
    for (int i=l;i<=r;i++) a[i]=b[i];
}

int main(){
    cin>>n;tot=0;
    for (int i=1;i<=n;i++) cin>>a[i];
    b_sort(1,n);
    for (int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

 

5.快速排序(手动标星)

时间复杂度O(nlog2(n))

如图所示(luogu上找的)炫酷*生动形象

原理:本质上是一种双向的收缩,然后每一次找一个参考点,使参考点的右边都大于这个点,左边都小于这个点

然后此时参考点的左边都小于参考点,右边都大于参考点,所以我们分别到两个区间里面做一样的事情

比如说以下一组数据

6 1 2 7 9 3 4 5 10 8

我先设基准点是6,然后设两个标记i和j,分别指向头和尾

我先用j从右边开始往左找,找到第一个小于基准点的值5

再用i从左边往右找,找到第一个大于基准点的值7,然后把找到的这两个值交换

(注:代码里写的稍有不同,是用不断覆盖的方式来实现的)

此时是:6 1 2 5 9 3 4 7 10 8

然后继续用j往左找,找到4,i往右找,找到9

交换,变成6 1 2 5 4 3 9 7 10 8

然后j再往左走找到3,i再往左走发现重合了

此时我们把3和参考点交换,得到3 1 2 5 4 6 9 7 10 8

此时在6左边的都小于6,在6右边的都大于6,然后分别对两个区间做一样的事情

(注:刚才的样例里面如果把3改成比参考点大的值,j一样会走到i也就是走到一个比参考点小的值,所以不会出错)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=105;
int n,Min,a[MAXN],tot,b[MAXN];

void qsort(int l,int r){
    int i=l,j=r,tmp;
    if (l<r){
        tmp=a[l];//设置参考点
        while (i!=j){
            while (i<j && a[j]>=tmp) --j;
            if (i<j) a[i++]=a[j];
            while (i<j && a[i]<tmp) ++i;
            if (i<j) a[j--]=a[i];
        }
        a[i]=tmp;//把最后的中间点变成参考点
        qsort(l,i-1);
        qsort(i+1,r);
    }
}
int main(){
    cin>>n;tot=0;
    for (int i=1;i<=n;i++) cin>>a[i];
    qsort(1,n);
    for (int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

(如果还是看不懂可以去看这个:快速排序

然后还有一种叫sort的东西......如果当你熟练掌握了快速排序可以去看一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值