(声明:方便起见,本文都说的是从小到大排)
1.选择排序
原理:先选一个最小的替换第一个,再选一个最小的替换第二个......
时间复杂度O()
参考代码:
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()
参考代码:
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()
用一张图来表示一下(借的百度的一张图)
参考代码:
#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()
如图所示(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的东西......如果当你熟练掌握了快速排序可以去看一下