• 算法导论1:插入排序和归并排序 2016.1.1


      最近一段时间的博客都是记录我读《算法导论》的文字,虽然很厚,但是一点一点来吧,总有一天会看完的。虽然只看了几页,感觉收获还挺多的,原来懂了算法,却不一定能做出最好的代码(姿势很重要啊Orz。。),果然要跟着导论学习正确的姿势。

    2016.1.1 今天看了两个算法:插入排序和归并排序。代码如下(C语言)

    插入排序

     1 #include<stdio.h>
     2 
     3 void insertsort(int *a,int n) //默认存储到a[1..n]中 
     4 {
     5     int i,j;
     6     j=2;
     7     for (j=2;j<=n;j++) {
     8         i=j-1;
     9         int key=a[j];
    10         while (i>0 && a[i]>key) {
    11             a[i+1]=a[i];
    12             i--;
    13         }
    14         a[i+1]=key;
    15     }
    16 }
    17 
    18 int main()
    19 {
    20     int n;
    21     int a[11]={};
    22     scanf("%d",&n);
    23     int i;
    24     for (i=1;i<=n;i++) {
    25         scanf("%d",&a[i]);
    26     }
    27     insertsort(a,n);
    28     for (i=1;i<=n;i++) {
    29         printf("%d |",a[i]);
    30     }
    31     return 0;
    32 }


    归并排序:

    #include<stdio.h>
    
    void merge(int *a,int *b,int l,int mid,int r)
    {
        int i=l;
        int j=mid+1;
        int cou=l;
        while (i<=mid && j<=r) {
            if (a[i]<a[j]) {
                b[cou]=a[i];
                i++;
                cou++;
            }
            else {
                b[cou]=a[j];
                j++;
                cou++;
            }
        }
        while (i<=mid) {
            b[cou]=a[i];
            i++;
            cou++;
        }
        while (j<=r) {
            b[cou]=a[j];
            j++;
            cou++;
        }
        for (i=l;i<=r;i++) {
            a[i]=b[i];
        }
    }
    
    void mergesort(int *a,int *b,int l,int r)
    {
        if (l<r) {
            int mid=(l+r)/2;
            mergesort(a,b,l,mid);
            mergesort(a,b,mid+1,r);
            merge(a,b,l,mid,r);
        }
    }
    
    int main()
    {
        int a[11]={},b[11]={};
        int n,i;
        scanf("%d",&n);
        for (i=0;i<n;i++) {
            scanf("%d",&a[i]);
        }
        mergesort(a,b,0,n-1);
        for (i=0;i<n;i++) {
            printf("%d |",a[i]);
        }
        return 0;
    }

    书中是通过这两个算法引出算法复杂度分析的思路,前者是一个n方的复杂度,后者是一个nlgn的复杂度。

    另外,练习题中有一个很具有思考价值的问题,就是在归并排序中对小数组采用插入排序。

    下面是引述书中的内容:

    “插入排序的最坏情况运行时间为Θ(n^2),但插入排序中的常数因子可能使得它在n较小时,在许多机器上实际运行得要更快。
    因此,在归并排序中当子问题变得足够小时,采用插入排序来使递归的叶变粗是有意义的。考虑对归并排序的一种修改。”

    那么,在递归树的哪一层开始采用插入排序呢?这是一个值得思考的问题。
    如果想看参考答案,可以看这里。http://clrs.skanev.com/02/problems/01.html

    下面是对上面两个算法综合之后的排序算法,代码:
    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h> 
    
    void merge(int *a,int *b,int l,int mid,int r)
    {
        int i=l;
        int j=mid+1;
        int cou=l;
        while (i<=mid && j<=r) {
            if (a[i]<a[j]) {
                b[cou]=a[i];
                i++;
                cou++;
            }
            else {
                b[cou]=a[j];
                j++;
                cou++;
            }
        }
        while (i<=mid) {
            b[cou]=a[i];
            i++;
            cou++;
        }
        while (j<=r) {
            b[cou]=a[j];
            j++;
            cou++;
        }
        for (i=l;i<=r;i++) {
            a[i]=b[i];
        }
    }
    
    void insertsort(int *a,int l,int r) 
    {
        int i,j;
        for (j=l+1;j<=r;j++) {
            i=j-1;
            int key=a[j];
            while (i>l-1 && a[i]>key) {
                a[i+1]=a[i];
                i--;
            }
            a[i+1]=key;
        }
    }
    
    void mixedmergesort(int *a,int *b,int l,int r)
    {
        if (l>=r) return ;
        if (r-l<20)  insertsort(a,l,r);
        else {
            int mid=(l+r)/2;
            mixedmergesort(a,b,l,mid);
            mixedmergesort(a,b,mid+1,r);
            merge(a,b,l,mid,r);
        }
    }
    
    int main()
    {
        int a[101]={},b[101]={};
        int n,i;
        scanf("%d",&n);
        srand(time(0));
        for (i=1;i<=n;i++) {
            a[i]=rand()%100+1;
        }
        mixedmergesort(a,b,1,n);
        for (i=1;i<=n;i++) {
            printf("%d |",a[i]);
        }
        return 0;
    }
  • 相关阅读:
    由二进制移位想到的
    KDJ指标详解
    PMP考试结束
    转K线理论初级二
    日本地震效应
    Baseline之流水先生的见解
    KDJ判断原则
    转K线理论初级一
    管理学法则
    今天提到KW,特此@Mark一下
  • 原文地址:https://www.cnblogs.com/itlqs/p/5093883.html
Copyright © 2020-2023  润新知