整理一下几个排序。
选择排序(时间复杂度是O(n^2)):
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
if(a[i]>a[j]) swap(a[i],a[j]);
}
}
冒泡排序(时间复杂度是O(n^2)):
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(a[j]>a[j+1]) swap(a[j],a[j+1]);
}
}
快速排序(时间复杂度是O(nlogn)):
快排的原理简单来讲就是把数放到正确的位置。
我们先选中一个数x,从指针左边开始向右移动找到一个比x要大的数,另一个指针从右边向左移动开始找到一个比x要小的数,然后交换找到的两个数,最后一直交换到指针指向同一个数,这个数的位置就是x应该在的位置。
因为此时x左边的数全部小于x,右边的数全部大于x,但是没有排序好。此时对x左边的数和x右边的数进行递归一直到全部排序好为止。
我的代码并没有将x填入正确的位置这一步,而是通过不断交换最后把x挤到正确的位置上,所以在递归调用的时候也需要把x包含进去。
void quick_sort(int a[],int l,int r){
//递归结束条件
if(l>=r) return;
//因为后面是用do while先进行++和--
int i=l-1,j=r+1,x=a[(l+r)/2];
//进入循环
while(i<j){
//从左边开始找到一个比x大的数
do i++;while(a[i]<x);
//从右边开始找到一个比x小的数
do j--;while(a[j]>x);
//此时再判断一下i是否小于j,如果小于则交换
if(i<j) swap(a[i],a[j]);
}
//递归剩下的数
quick_sort(a,l,j);
quick_sort(a,j+1,r);
}
归并排序(时间复杂度是O(nlogn)):
归并排序的原理是将序列不断分成更小的子序列,然后对子序列进行排序之后再将排序好的子序列归到一起(归到一起的时候也要进行排序)。
先用一个函数不断递归将序列分成几个最小子序列,然后将这几个最小子序列排序,一直排序到完整序列为止。
void Merge(int l,int m,int r){ //对归并的子序列进行排序
int i=l,j=m+1,k=i;
int temp[100005];
while(i<=m&&j<=r){ //对两个序列进行比较
if(a[i]<=a[j])
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=m) temp[k++]=a[i++]; //将后面还未存入temp的数存入
while(j<=r) temp[k++]=a[j++]; //和上面的循环之间只会实现一个
for(i=l;i<=r;i++){ //将临时数组temp的值赋给a
a[i]=temp[i];
}
}
void Mergesort(int l,int r){ //归并主函数
if(l>=r) return; //递归的终止条件
int m=(l+r)/2;
Mergesort(l,m); //从左边开始递归
Mergesort(m+1,r); //从右边开始递归
Merge(l,m,r); //调用函数对子序列进行排序
}
sort函数(时间复杂度是O(nlogn)):
sort函数是c++库里自带的一个算法。一般情况下是对快排的优化,在实际应用中也比快排快,不过据说有得大牛写得快排比sort快。
sort包含在头文件#include<algorithm>
中。
sort函数有三个参数,
第一个参数:要排序的数组的起始位置
第二个参数:排序的数组的结束位置(最后一个数据的后一位)
第三个参数:排序的方法(可以不填,默认的方法是升序)
具体可以看这篇博客:指路
下面是实现代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<sstream>
#define ll long long
using namespace std;
int a[100005];
bool cmp(int a,int b){
return a>b;
}
int main(int argc,char const*argv[]){
int n=10;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n); //这是默认的升序排序
sort(a,a+n,cmp); //这是自己定义的降序排序
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
return 0;
}