码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论5:基数排序 2016.1.5

时间:2016-01-06 00:11:29      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

  今天的这个比较神奇,是一个线性复杂度的排序算法O(n),算法导论在这一部分先证明了比较排序的复杂度下界是nlgn,所以基数排序不是基于比较的排序。

  其实这种比较方法我们应该都接触过。假设输入的数都是三位以下的数(当然其他位数也可以,类比一下,这里就假设是三位数、两位数、一位数),那么只需要大致3n的复杂度就可以排好序。过程是这样:

  先设置辅助空间t[0..9][n]

  然后扫第一遍n个数,个位是几就放在t[几]那一行。然后扫一遍t数组,按顺序放回原数组中

  然后扫第二遍n个数,十位是几就放在t[几]那一行。然后扫一遍t数组,按顺序放回原数组中

  然后扫第三遍n个数,百位是几就放在t[几]那一行。然后扫一遍t数组,按顺序放回原数组中

 现在原数组已经是按顺序排好的了。其实就是最原始的比较方法,先比较个位,再比较十位,再比较百位。

代码如下:(这里为了好理解先用冗长的代码,其实这里的代码还可以再简化,然后修改以后适用于任何位数)

#include<stdio.h>
#include<string.h>

int t[10][20];
int cou[10];

void jishusort(int *a,int l,int r)
{
    memset(cou,0,sizeof(cou));
    memset(t,0,sizeof(t));
    int i;
    for (i=l;i<=r;i++) {
        int k=a[i]%10;
        t[k][cou[k]]=a[i];
        cou[k]++;
    }
    int c=l;
    for (i=0;i<=9;i++) {
        int j;
        for (j=0;j<cou[i];j++) {
            a[c]=t[i][j];
            c++;
        }
    }
    memset(cou,0,sizeof(cou));
    memset(t,0,sizeof(t));
    for (i=l;i<=r;i++) {
        int k=a[i]/10%10;
        t[k][cou[k]]=a[i];
        cou[k]++;
    }
    c=l;
    for (i=0;i<=9;i++) {
        int j;
        for (j=0;j<cou[i];j++) {
            a[c]=t[i][j];
            c++;
        }
    }
    memset(cou,0,sizeof(cou));
    memset(t,0,sizeof(t));
    for (i=l;i<=r;i++) {
        int k=a[i]/100;
        t[k][cou[k]]=a[i];
        cou[k]++;
    }
    c=l;
    for (i=0;i<=9;i++) {
        int j;
        for (j=0;j<cou[i];j++) {
            a[c]=t[i][j];
            c++;
        }
    }        
}

int main()
{
    int n;
    scanf("%d",&n);
    int i;
    int a[20]={};
    for (i=1;i<=n;i++) {
        scanf("%d",&a[i]);
    }
    jishusort(a,1,n);
    for (i=1;i<=n;i++) {
        printf("%d |",a[i]);
    }
    return 0;
}

 

在这之前,书中还讲了一个计数排序,也是一种线性复杂度的算法。大体思想是这样:如果输入的数一定在1..k之间,那么对于每一个输入的元素x,确定出小组x的元素个数。利用这一信息就可以直接把x放在输出数组的相应位置了。算法导论里的伪代码真的太厉害了,用了几个线性的操作就实现了上面的思想。今天太晚了就不打代码了,把书上的伪代码贴在这里。

技术分享

 

可以注意到上面两个算法基本上只适用于排整数。
然后书上又讲了桶排序,目测虽然思想和基数排序差不多,但好像略复杂一些,以后有机会再研究。部分习题也不好意思先略过了。

算法导论5:基数排序 2016.1.5

标签:

原文地址:http://www.cnblogs.com/itlqs/p/5104074.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!