算法导论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;
}

 

posted @ 2016-01-01 22:25  lvmememe  阅读(586)  评论(0编辑  收藏  举报