欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

排序问题(一维偏序)各种解法(选择排序,冒泡排序,桶排序,sort排序,归并排序)

程序员文章站 2022-03-03 08:22:59
...

前言

最近学了偏序问题,什么CDQ分治、树套树、CDQ套CDQ、CDQ加树状数组、CDQ加线段树……到一边去吧!~~

题目描述

给你一个数n,接下来一行输入n个数a[i] (1in),求它们从小到大的排序。
样例输入:
6
3 2 7 1 6 5
样例输出:
1 2 3 5 6 7

数据范围

随接下来作者所讲方法变化而变化~~~

方法一:选择排序/冒泡排序

数据范围:n5103,每个数0<a[i]109
时间均为O(n2)
选择排序原理:从小到大枚举每个位置,然后从这个位置开始到最后中找数,每次确定一个位置上的数.

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 5000
int a[MAXN+5];
int main(){
    scanf("%d",&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]);
    printf("%d",a[1]);
    for(int i=2;i<=n;i++)
        printf(" %d",a[i]);
    printf("\n");
    return 0;
}

(Bubble Sort)
冒泡排序原理:它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最小的元素就在数列的前面! 采用相同的方法再次遍历时,第二小的元素就被排列在当前最小元素之后。

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 5000
int a[MAXN+5];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<i;j++)
            if(a[j]>a[j+1])//交换位置
                swap(a[j],a[j+1]);
    printf("%d",a[1]);
    for(int i=2;i<=n;i++)
        printf(" %d",a[i]);
    printf("\n");
    return 0;
}

方法二:桶排序(Barrel Sort)

数据范围:n107,每个数0<a[i]107
将每个a[i]加入一个以值为下标的桶中,然后从最小到最大找一遍:
时间不稳定

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 10000000
#define INF 0x3f3f3f3f
int a[MAXN+5];
bool Barrel[MAXN+5];
int main(){
    int Min=INF,Max=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]),Barrel[a[i]]=1;
        Min=min(Min,a[i]);
        Max=max(Max,a[i]);
    }
    int flag=0;
    for(int i=Min;i<=Max;i++)
        if(Barrel[i]){
            if(!flag) flag++,printf("%d",i);
            else printf(" %d",i);
        }
    printf("\n");
    return 0;
}

方法三:sort排序

数据范围:排序所能给出的最大范围
调用algorithm库下的sort排序函数
时间O(nlogn)

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 1000000
#define INF 0x3f3f3f3f
int a[MAXN+5];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    printf("%d",a[1]);
    for(int i=2;i<=n;i++)
        printf(" %d",a[i]);
    printf("\n");
    return 0;
}

方法三:归并排序

利用分治的思想把整个序列排序
时间O(nlogn)

#include<cstdio>
#include<algorithm>
#define MAXN 100000
using namespace std;
int n,a[MAXN+5],tmp[MAXN+5];
void Merge(int l,int m,int r){
    int p=l,q=m+1,len=l;
    while(p<=m&&q<=r){
        if(a[p]<=a[q]) tmp[len++]=a[p++];
        else tmp[len++]=a[q++];
    }
    while(p<=m) tmp[len++]=a[p++];
    while(q<=r) tmp[len++]=a[q++];
    for(int i=l;i<=r;i++)
        a[i]=tmp[i];
    return ;
}
void MergeSort(int l,int r){
    if(l==r) return ;
    int mid=(l+r)>>1;
    MergeSort(l,mid);
    MergeSort(mid+1,r);
    Merge(l,mid,r);
    return ;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    MergeSort(1,n);
    printf("%d",a[1]);
    for(int i=2;i<=n;i++)
        printf(" %d",a[i]);
    printf("\n");
    return 0;
}