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

    最近正好计导和c语言都讲到排序问题,以前都是了解概念之后直接用sort,这次把各种排序算法都代码实现一下。

    题目传送门

     

    插入排序

    把序列分成两部分,前一部分为已排好序部分,后一部分未排序。(初始1~1为已排序部分,2~n为未排序部分)

    然后从未排序部分中取一个数,将其加入已排序部分的对应位置中。

    代码实现:

     1 // 插入排序  升序 
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std ;
     8 const int N = 100000 + 10 ;
     9 
    10 inline int read() {
    11     int k = 0, f = 1 ; char c = getchar() ;
    12     for( ; !isdigit(c) ; c = getchar())
    13       if(c == '-') f = -1 ;
    14     for( ; isdigit(c) ; c = getchar())
    15       k = k*10 + c-'0' ;
    16     return k*f ;
    17 } 
    18 
    19 int n ;
    20 int hh[N] ;
    21 
    22 int main() {
    23     n = read() ;
    24     for(int i=1;i<=n;i++) hh[i] = read() ;
    25     for(int i=2;i<=n;i++) {
    26         int t = hh[i] ;
    27         for(int j=1;j<i;j++) {    // 新加入一个未排序的数 
    28             if(hh[j] > t) {   // 在已经排好序的数据中找到第一个比它大的数 
    29                 for(int k=i;k>j;k--) hh[k] = hh[k-1] ;  // 比它大的数都后移一位
    30                 hh[j] = t ; 
    31                 break ;
    32             }
    33         }
    34     }
    35     for(int i=1;i<=n;i++) printf("%d ",hh[i]) ;
    36     return 0 ;
    37 }

    复杂度:O(n^2)  (严格)

    选择排序

    每次从未排序序列中找到最小的数,加入已排序序列的末尾

    代码实现:

     1 // 选择排序  升序 
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std ;
     8 const int N = 100000 + 10 ;
     9 const int INF = 0x7ffffff ;
    10 
    11 inline int read() {
    12     int k = 0, f = 1 ; char c = getchar() ;
    13     for( ; !isdigit(c) ; c = getchar())
    14       if(c == '-') f = -1 ;
    15     for( ; isdigit(c) ; c = getchar())
    16       k = k*10 + c-'0' ;
    17     return k*f ;
    18 } 
    19 
    20 int n ;
    21 int hh[N] ;
    22 
    23 int main() {
    24     n = read() ;
    25     for(int i=1;i<=n;i++) hh[i] = read() ;
    26     for(int i=1;i<=n;i++) {  
    27         int minn = INF, pp ;   // pp记录最小值位置 
    28         for(int j=i;j<=n;j++) {   
    29             if(hh[j] < minn) {
    30                 minn = hh[j] ;  pp = j ;
    31             }
    32         }
    33         for(int j=pp;j>i;j--) hh[j] = hh[j-1] ;   // 元素后移 
    34         hh[i] = minn ;
    35     }
    36     for(int i=1;i<=n;i++) printf("%d ",hh[i]) ;
    37     return 0 ;
    38 }

    复杂度:O(n^2)(严格) (比插入排序常数更大些)

    冒泡排序:

    执行n轮,对于每轮:

    扫一遍数组,如果发现一个元素比它的后继元素大,就交换它们

    代码:

     1 // 冒泡排序  升序 
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std ;
     8 const int N = 100000 + 10 ;
     9 const int INF = 0x7ffffff ;
    10 
    11 inline int read() {
    12     int k = 0, f = 1 ; char c = getchar() ;
    13     for( ; !isdigit(c) ; c = getchar())
    14       if(c == '-') f = -1 ;
    15     for( ; isdigit(c) ; c = getchar())
    16       k = k*10 + c-'0' ;
    17     return k*f ;
    18 } 
    19 
    20 int n ;
    21 int hh[N] ;
    22 
    23 int main() {
    24     n = read() ;
    25     for(int i=1;i<=n;i++) hh[i] = read() ;
    26     for(int i=1;i<n;i++) {
    27         for(int j=1;j<=n-i;j++)
    28           if(hh[j] > hh[j+1]) swap(hh[j],hh[j+1]) ;
    29     }
    30     for(int i=1;i<=n;i++) printf("%d ",hh[i]) ;
    31     return 0 ;
    32 }

    复杂度:O(n^2) (严格) 

    不过可以优化一下,就是对于每一轮做一个标记,如果发现该轮中一次swap都没有做,就说明数组已排序完毕,就可以break了。

    桶排序:

    假如数据为0~500000内的整数,那我们就假设有500001个桶,编号分别为0~500000。

    对于数组中的每一个数,将其放到对应的桶中。

    最后从小到大遍历每个桶,将其中的数输出出来即可。

    代码:

     1 // 桶排序  升序 
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std ;
     8 const int N = 100000 + 10 ;
     9 const int M = 500000 + 10 ; 
    10 const int INF = 0x7ffffff ;
    11 
    12 inline int read() {
    13     int k = 0, f = 1 ; char c = getchar() ;
    14     for( ; !isdigit(c) ; c = getchar())
    15       if(c == '-') f = -1 ;
    16     for( ; isdigit(c) ; c = getchar())
    17       k = k*10 + c-'0' ;
    18     return k*f ;
    19 } 
    20 
    21 int n ;
    22 int buc[M] ;
    23 
    24 int main() {
    25     n = read() ;
    26     for(int i=1;i<=n;i++) buc[read()]++ ;
    27     for(int i=0;i<=500000;i++) {
    28         while(buc[i]--) printf("%d ",i) ;
    29     }
    30     return 0 ;
    31 }

    复杂度:O(n+m) m表示数据范围

    桶排序只适用于数据范围较小,且数据均为整数(或类似)的情况。不过对于非整形数据,我们有时可以将其离散化,然后适用桶排序。

    桶排序较其他排序方式较为特殊,有些情况下会起到出人意料的效果!

    快速排序:

    对于一段未排序的序列,选取一个sdd(标准数),将小于标准数的放入一个序列,大于等于标准数的放入另一个序列,然后再递归处理两个子序列。

    代码:

    // 快速排序  升序 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std ;
    const int N = 100000 + 10 ;
    const int M = 500000 + 10 ; 
    const int INF = 0x7ffffff ;
    
    inline int read() {
        int k = 0, f = 1 ; char c = getchar() ;
        for( ; !isdigit(c) ; c = getchar())
          if(c == '-') f = -1 ;
        for( ; isdigit(c) ; c = getchar())
          k = k*10 + c-'0' ;
        return k*f ;
    } 
    
    int n ;  int hh[N] ;
    
    void q_sort(int l,int r) {
        
    //    int mid = (l+r)>>1 ;
    //    printf("
    l,r:%d,%d",l,r) ;
        
        if(l >= r) return ;
        int ll = l, rr = r ;  int sdd = hh[ll] ;
        while(ll < rr) {
            while(hh[ll] < sdd && ll < r) ll++ ;
            while(hh[rr] >= sdd && rr > l) rr-- ;
            if(ll >= rr) break ;
            swap(hh[ll],hh[rr]) ;
        }
        int mm = rr ;
        
    //    for(int i=1;i<=3;i++) printf("%d ",hh[i]) ;  printf("
    ") ;
    //    printf("
    mm:%d
    ",mm) ;
        
        q_sort(l,mm) ; q_sort(mm+1,r) ;
    }
    
    int main() {
        n = read() ;
        for(int i=1;i<=n;i++) hh[i] = read() ;
        q_sort(1,n) ;
        for(int i=1;i<=n;i++) printf("%d ",hh[i]) ;
        return 0 ;
    }

    复杂度:O(nlogn)   (理想) 

    归并排序:

    先将待排序序列平均分成两个序列,递归处理。

    待两个子序列排好序后,依次比较两个子序列中最小的数,将其提取出来,放入新的序列中。

    代码:

     1 // 归并排序 升序 
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std ;
     7 const int N = 100000 + 10 ;
     8 
     9 inline int read() {
    10     int k = 0, f = 1 ; char c = getchar() ;
    11     for( ; !isdigit(c) ; c = getchar())
    12       if(c == '-') f = -1 ;
    13     for( ; isdigit(c) ; c = getchar())
    14       k = k*10 + c-'0' ;
    15     return k*f ;
    16 }
    17 
    18 int n ;  int hh[N], gg[N] ;
    19 
    20 void m_sort(int l,int r) {
    21     if(l == r) return ;
    22     int mid = (l+r)>>1 ;
    23     m_sort(l,mid) ; m_sort(mid+1,r) ;
    24     int l1 = l, l2 = mid+1 ;
    25     int now = l ;
    26     for(int i=l;i<=r;i++) {
    27         if(l1 > mid) {
    28             gg[now++] = hh[l2++] ;
    29         } else if(l2 > r) {
    30             gg[now++] = hh[l1++] ;
    31         } else {
    32             if(hh[l1] < hh[l2]) {
    33                 gg[now++] = hh[l1++] ;
    34             } else gg[now++] = hh[l2++] ;
    35         }
    36     }
    37     for(int i=l;i<=r;i++) hh[i] = gg[i] ;
    38 }
    39 
    40 int main() {
    41     n = read() ;
    42     for(int i=1;i<=n;i++) hh[i] = read() ;
    43     m_sort(1,n) ;
    44     for(int i=1;i<=n;i++) printf("%d ",hh[i]) ;
    45     return 0 ;
    46 }

    复杂度:O(nlogn)  (严格)

    上述代码为二路归并,其实也可以多路归并。

    不正经系列待更新~

  • 相关阅读:
    springboot获取application.yml中的配置信息
    springboot+mybatis整合(单元测试,异常处理,日志管理,AOP)
    最近工作中的一些教训
    SAP BADI的“多次使用”(multiple use)
    SAP CRM 忠诚度相关表的关系图
    一个噩梦
    i.s.h.med Enhancement for cancelling an appointment
    一个冷门语言开发者的2016年总结和2017年目标
    装机的几个误区
    关于BAPI_PATIENT_CREATE(病患主数据创建)
  • 原文地址:https://www.cnblogs.com/zub23333/p/11656601.html
Copyright © 2011-2022 走看看