排序
选择排序
//选择排序的核心思想是找到一个最小的元素(第二层循环中ji就是最小元素在无序数组中的编号)然后把它放到最前面
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a[99999999],n;
void swap(int &l,int &k){
int t=l;
l=k;
k=t;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
int ji=i;
for(int j=i+1;j<=n;j++){
if(a[j]<a[ji])ji=j;
}
if(ji!=i)
// {//或者这样也行
// int t=a[i];
// a[i]=a[ji];
// a[ji]=t;
// }
swap(a[i],a[ji]);//要传址调用
}
cout<<endl;
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
正版冒泡
//冒泡排序的核心思想是一遍一遍地比较相邻两个数并交换顺序
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],n;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=n-1;i>=1;i--){
for(int j=0;j<=i;j++){
if(a[j]>a[j+1]) swap(a[j],a[j+1]);
}
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
盗版冒泡
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],n;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(a[i]>a[j]) swap(a[i],a[j]);
}
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
插排
//顾名思义
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],n,i,j;
void yi(int p,int q)
{
for(int h=q;h>p;h--)a[h]=a[h-1];
}
int main(){
cin>>n;
for( i=1;i<=n;i++)scanf("%d",&a[i]);
for( i=2;i<=n;i++){//a[i]为需要插入的数
for( j=i-1;j>=1;j--)//寻找插入点
if(a[j]<a[i])break;
if(j!=i-1){//需要将a[i]插入a[j]后
int temp=a[i];
yi(j+1,i);
a[j+1]=temp;
}
}
cout<<endl;
for(i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
桶排
//开一个数组记录所有数字出现了几次,最后按数组顺序输出
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],n,ji;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&ji);
a[ji]++;
}
for(int i=0;i<=n;i++){
while(a[i]){
printf("%d ",i);
a[i]--;
}
}
return 0;
}
快速排序
#include<bits/stdc++.h>
using namespace std;
int n,a[100005];
int read(){//快读优化
int x=0;char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
void quick_sort(int l,int r){
if(l>=r)return ;
int mid=a[(l+r)>>1],i=l,j=r;//我习惯用将基准数设为中间的那个数
while(i<=j){
while(a[i]<mid)++i;//不能加‘=’,否则当mid为整个数组中的最大数时会陷入死循环
while(a[j]>mid)--j;
if(i<=j){//要特判,否则i>j了就是在帮倒忙了
swap(a[i],a[j]);
++i,--j;//不在原地踏步
}
}
if(l<j)quick_sort(l,j);//!!! 一遍快排之后i>j了所以~
if(r>i)quick_sort(i,r);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
a[i]=read();
}
quick_sort(1,n);
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
}
三数取中+冒泡版 快排
//
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],n;
void cha(int p,int q){//p<q
int ji=0,j;
for(int i=p+1;i<=q;i++){
for(j=p;j<i;j++)if(a[i]<a[j])break;
ji=a[i];
for(int k=i-1;k>=j;k--){//千万记得是倒序赋值
a[k+1]=a[k];
}
a[j]=ji;
}
}
void quick(int le,int ri){
if(le>=ri)return;
if(ri-le<=10)cha(le,ri);
int t=(le+ri)/2,mid,x=le,y=ri;//在左端点右端点和中点位置的三个数中选取大小排中间的数,并将另外两数按大小分别赋给左右端点
if(a[le]<a[t]){
if(a[t]>a[ri]){
int w=a[t];
a[t]=a[ri];
a[ri]=w;
}
}
if(a[le]>a[t]){
int w=a[t];
a[t]=a[le];
a[le]=w;//a[le]<a[t]
if(a[t]>a[ri]){
int w=a[t];
a[t]=a[ri];
a[ri]=w;
}
}
mid=a[t];
while(x<=y){
while(a[x]<mid)x++;
while(a[y]>mid)y--;
if(x<=y){
int w=a[x];
a[x]=a[y];
a[y]=w;
x++;
y--;
}
}
if(le<y)quick(le,y);
if(x<ri)quick(x,ri);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
quick(1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
归并排序
#include<iostream>
#include<cstdio>
using namespace std;
int a[99999999],b[99999999],n;
void gui(int le,int ri)
{
if(le==ri)return;
int mid=(le+ri)/2,x=le,y=mid+1,k=le;
gui(le,mid);
gui(mid+1,ri);
while(x<=mid&&y<=ri)
if(a[x]<a[y])b[k++]=a[x++];
else b[k++]=a[y++];
while(x<=mid)b[k++]=a[x++];
while(y<=ri)b[k++]=a[y++];
for(int g=le;g<=ri;g++)a[g]=b[g];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
gui(1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
基数排序
基数排序的核心思想是按顺序(从高往低或者从低往高)比较每个数字的个位十位百位等等,每次按当前数位上的数值大小将数组重新排列,然后将新数列按下一位上的数值大小比较并再次排序,以此类推即可得到答案
#include<iostream>
#define ll long long
using namespace std;
ll ma,n,a[200000],tub[15][200000],bas[15]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000},k;
int main(){
cin>>n;
for(ll i=1;i<=n;i++){
cin>>a[i];
ll t=1;
while(a[i]>=bas[t])++t;
ma=max(ma,t);//统计有多少位
}
for(ll t=1;t<=ma;t++){
for(ll i=1;i<=n;i++){
k=(a[i]%(bas[t]))/bas[t-1];tub[k][++tub[k][0]]=a[i];//按当前位大小放入桶子里
}
ll now=1;
for(ll i=1;i<=n;i++)
for(k=0;k<=9;k++){
for(ll ji=1;ji<=tub[k][0];ji++)
a[now++]=tub[k][ji];//按桶子的顺序重新排序
tub[k][0]=0;//记录桶子里有多少个数
}
}
for(ll i=1;i<=n;i++)cout<<a[i]<<" ";
}
测试数据生成器
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int main(){
freopen("testdata.in","w",stdout);
srand((unsigned)time(NULL));
for(int i=1;i<=10000;i++)
printf("%d ",rand());
return 0;
}