排序算法 基数排序

转自:http://blog.csdn.net/yabber0914/article/details/52279537

(一)基数排序的思想:

不直接比较数与数的大小。把待排序的整数按位分,分为个位,十位…..从小到大依次将位数进行排序。
实际上分为两个过程:分配和收集。

分配就是:从个位开始,按位数从小到大把数据排好,分别放进0–9这10个桶中;
收集就是:依次将0-9桶中的数据放进数组中

重复这两个过程直到最高位

(二)过程:

比如现在要排序 {400,31,53,72,6,29}

首先按个位的大小依次排序,排序结果如下:
这里写图片描述
按十位进行排序,结果如下:
这里写图片描述
按百位排序后,结果如下:
这里写图片描述

(三)代码如下:

    public static void main(String[] args) {
        int[] arr={1200,121,292,72,12,233,44};      
        radixSort(arr,10,4);
        showArr(arr);
        //12 44 72 121 233 292 1200  
    } 

    //基数排序
    /** 
     * @param arr 待排序数组 
     * @param radix 基数(10,盒子个数) 
     * @param d 待排序中,最大的位数 
     * */  
    public static void radixSort(int[] arr,int radix,int d){
        int length=arr.length;
        int[] temp=new int[length];//用于暂存元素
        int[] count=new int[radix];//用于记录待排序元素的信息,用来表示该位是i的数的个数 
        int divide=1;

        for(int i=0;i<d;i++){
            //重置count数组,开始统计下一个关键字  
            Arrays.fill(count,0);
            //将arr中的元素完全复制到temp数组中
            System.arraycopy(arr,0,temp,0,length);

            //计算每个待排序数据的子关键字
            for(int j=0;j<arr.length;j++){
                int subKey=(temp[j]/divide)%radix;
                count[subKey]++;
            }

            //统计count数组的前j位(包含j)共有多少个数
            for(int j=1;j<radix;j++){
                count[j]=count[j]+count[j-1];
            }

            //按子关键字对指定的数据进行排序,因为开始是从前往后放,现在从后往前读取,保证基数排序的稳定性
            for(int j=arr.length-1;j>=0;j--){
                int subKey=(temp[j]/divide)%radix;
                count[subKey]--;    
                arr[count[subKey]] = temp[j]; 
              //插入到第--count[subKey]位,因为数组下标从0开始
            }

            divide = divide * radix; // 1 10 100    
        }       
    }

(四)说明:

分配的时间复杂度为O(n)
收集的的时间复杂度为O(radix)
分配和收集共需要distance趟,
所以基数排序的时间复杂度为O(d(n+r))
我们可以看出,基数排序的效率和初始序列是否有序没有关联。

整数时长度10W以上,最大值100W以下效率最好
比其他排序好在可以适用字符串,或者其他根据多个条件排序的场景,如日期(先按日排,月排,年排)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值