浅谈排序

浅谈排序

排序


桶排序

基本思想:每读入的数据x,桶a[x]就加一,输出时按桶的顺序,桶里有几个数就输出几次。

缺点:桶的数量取决于数据的大小,那就面临着MLE的问题,比如x在int范围内时,我们就要开2^16个桶,这非常的浪费空间,而且当带排序数据的类型为浮点数是,那就呵呵了,因为桶的标号只能是整数,总的来说,桶排序的使用范围并不广。

实现起来简单粗暴,只要不怕MLE就可以大胆上,时间复杂度真的是没毛病,数据个数n+桶的个数m,常数忽略不计O(m+n)。

来波代码,其实真的简单。

#include<bits/stdc++.h>
using namespace std;
int a[11010],n,x,maxn=-1;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d",&x);
        ++a[x];
        maxn=max(maxn,x);
    }
    for(int i=1;i<=maxn;i++)
        while(a[i]--) printf("%d ",i);
    return 0; 
}

冒泡排序

基本思想:每次比较两个相邻的元素,如果他们的顺序错误就把他们交换位置。

缺点:一个字:慢

这个代码的时间复杂度真的令人无语,两重循环,外层跑n-1次冒泡(最坏情况),内层跑1~n-i(后面i-1个数已经拍好),所以时间复杂度O(n^2)。

个人认为,既然有快排的存在,冒泡排序实在没有太多实际用途。

废话不多说,直接上代码。(从小到大)

#include<bits/stdc++.h>
using namespace std;
int n,a[10020];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<n;i++)//最坏的情况只需跑n-1次
        for(int j=1;j<=n-i;j++)//后i-1位一定已排好
            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;
} 

归并排序

基本思想:二分大法,将数列不断二分,直到只剩一个元素为止,然后不断向上归并,归并时已经可以保证两个子数列已经排序完成,所以可以用两个指针分别指向两个子序列的首部,比较将较小的一个放到一个新数组里,然后指针++。

其实c++里有一个merge_sort函数,就是用的归并排序,可以直接调用。

不过话说这归并排序几乎只有两个用途: 一是排序(不如快速排序快),二是求逆序对(需要手写函数),所以总的来说,上文中的merge_sort并没有太多用处。但是思想总是有用的,还是应学习一下。

时间复杂度:O(NlogN)。

贴代码

#include<iostream>
#include<cstdio>
#include<cstring> 
using namespace std;
int a[1001],b[1001];
int n;
void my_gb_sort(int l,int r)
{
    if(l==r) return;
    int m=(l+r)/2;
    my_gb_sort(l,m);
    my_gb_sort(m+1,r);
    int p1=l,p2=m+1;
    for (int i=l;i<=r;i++)
    {
        if (p1<=m && p2<=r) {
            if (a[p1]<a[p2]) b[i]=a[p1++];
            else b[i]=a[p2++];
        }
        else
        {
            if (p1<=m) b[i]=a[p1++];
            else b[i]=a[p2++];
        }
    }
    for(int i=l;i<=r;i++)
        a[i]=b[i];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    my_gb_sort(1,n);
    for(int i=1;i<=n;i++)
        printf("%d ",a[i]);
    return 0;
}

快速排序

sort大法好!!

咳咳,回正题,快速排序是一种基于二分思想的算法:每次随机选择一个序列中的数字temp作为基准点,然后以它为基准将比它小的数字放到他的左边,把比他大的放到他的右边然后再对他两侧的序列做相同的操作。

具体的操作是用两个指针对序列进行扫描实现的,i指针从左向右扫描,j指针从右向左扫描,直到i遇到比temp大的数,j遇到比temp小的数或i=j是停止。然后将两个数字交换。

快速排序的时间复杂度最差为0(n^2),但它的平均复杂度为O(nlogn),是最常用的排序算法。

#include<bits/stdc++.h>
using namespace std;
int n,a[20010];
void qsort(int l,int r)
{
    if(l>r) return;
    int temp=a[l];
    int i=l,j=r;
    while(i!=j)
    {
        while(a[j]>=temp&&i<j)
            --j;
        while(a[i]<=temp&&i<j)
            ++i;
        if(i<j) swap(a[i],a[j]);
    }
    a[l]=a[i];
    a[i]=temp;
    qsort(l,i-1);
    qsort(i+1,r);
    return;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    qsort(1,n);
    for(int i=1;i<=n;i++) printf("%d ",a[i]);
    return 0;
} 

 

关于排序我就说这些,等我成长为神犇,再回来补充吧。

特别推荐《啊哈!算法》,鄙人就是从这本书上学的排序,讲的生动,形象,易懂,确实是一本难得的好书。

posted @ 2018-06-28 14:13  Christopher_Yan  阅读(144)  评论(0编辑  收藏  举报