zoukankan      html  css  js  c++  java
  • 浅谈排序

    浅谈排序

    排序


    桶排序

    基本思想:每读入的数据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;
    } 

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

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

  • 相关阅读:
    unit3d 4.6 document open solution
    Unity3dBug
    linq to xml
    A const field of a reference type other than string can only be initialized with null Error [duplicate]
    Redis数据类型
    redis快照与AOF
    redis实现高并发下的抢购/秒杀功能
    xss攻击怎么防止
    四种常见的索引类型
    什么是sql 注入及如何预防 sql 注入
  • 原文地址:https://www.cnblogs.com/yanyiming10243247/p/9238425.html
Copyright © 2011-2022 走看看