基数排序

基数排序Radix sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机(Tabulation Machine)上的贡献。

它是这样实现的:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。

本文地址:http://www.cnblogs.com/archimedes/p/radix-sort-algorithm.html,转载请注明源地址。

举例

以LSD为例,假设原来有一串数值如下所示:
73, 22, 93, 43, 55, 14, 28, 65, 39, 81

第一步

首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
0
1    8 1
2    2 2
3    7 3 9 3 4 3
4    1 4
5    5 5 6 5
6
7
8    2 8
9    3 9

第二步

接下来将这些桶子中的数值重新串接起来,成为以下的数列:
81, 22, 73, 93, 43, 14, 55, 65, 28, 39
接着再进行一次分配,这次是根据十位数来分配:
0
1     14
2     228
3     39
4     43
5     55
6     65
7     73
8     81
9     93

第三步

接下来将这些桶子中的数值重新串接起来,成为以下的数列:
14,  22,  28,  39,  43,  55,  65,  73,  81,  93
这时候整个数列已经排序完毕; 如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止

算法实现

下面的代码源自维基,原代码是用C++描述的,这里改为C描述,增加了部分注释便于理解,由于代码中有几处很精妙,很值得学习

public class BaseSort {

    public void sort(int[] array) {
        int maxBit = findBitCount(array);
        int[] tmp = new int[array.length];
        //0-9的桶
        int[] count = new int[10];
        int radix = 1;
        //比较maxBit次
        for (int i = 0; i < maxBit; i++) {
            //开始前清空桶
            for (int j = 0; j < count.length; j++) {
                count[j] = 0;
            }
            //统计每个桶中的记录数
            for (int j = 0; j < array.length; j++) {
                //求得某一个的数
                int k = (array[j] / radix) % 10;
                count[k]++;
            }
            //第j个桶以及之前所有桶中元素的总数
            for(int j = 1; j < 10; j++){
                count[j] = count[j - 1] + count[j];
            }

            //重新排序数组
            for (int j = array.length-1; j >= 0; j--) {
                int k = (array[j] / radix) % 10;
                tmp[count[k] - 1] = array[j];
                count[k]--;
            }

            //将临时数组的内容复制到array数组中
            for (int j = 0; j < array.length; j++) {
                array[j] = tmp[j];
            }

            radix *= 10;
        }
    }

    //求数组中最大的位数
    public int findBitCount(int[] array) {
        int d = 1; //保存最大的位数
        int p = 10;
        for(int i = 0; i < array.length; ++i) {
            while(array[i] >= p) {
                p *= 10;
                ++d;
            }
        }
        return d;
    }

    public static void main(String[] args) {
        int[] array = {73, 22, 93, 43, 55, 14, 28, 65, 39, 81};
        BaseSort baseSort = new BaseSort();
        baseSort.sort(array);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }
}


效率分析

时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。

空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。

所以时间复杂度为:O(d(n+radix))


转自:http://www.cnblogs.com/wuyudong/p/radix-sort-algorithm.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值