小白懂算法之基数排序

一.基数排序介绍

  基数排序通过元素的各个位的值;放到对应的桶里面;比如元素456,目前在十位数,那么456的十位数为5,那456就放到桶中下标为5的位置。

二.算法思想

  把元素统一为同样长度的数组长度 (长度依据元素中最大的那个数),元素较短的数前面补0,比如(1 15 336   看成  001 015 336)

  然后从最低位开始,以此进行排序。

三.图解

 

 

 

 

 

 

四.代码实现(Java实现)

    public static void main(String[] args) {
        //准备一个待排序的数组
        int arr[] = {53, 3, 542, 748, 14, 214,11,1110,120,210};
        //调用基数排序算法
        radixSort(arr);
        //遍历排序后的数组
        System.out.println("排序后的数组:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }
    /**
     *     实现思路:
     *         1.确定arr中数组的最大数,得到最大数的长度,这个长度是用来限制循环的次数
     *         2.准备一个二维数组,二维数组每个一维数组用来存储在指定的位数上相同的元素
     *         3. 还需要准备一个一维数组everyBucketNum,这个一维数组的作用记录二维数组中每个位置上的元素的个数,为什么要这样做呢?我下面解释下:
     *             》我们使用二维数组在保持元素时,一定会存在空的桶,也就是默认为0的情况,我想问的是,如果我们直接遍历这个
     *             二维数组,你怎么知道里面的元素0是待排序数组中的还是空桶?
     *         4.两层循环:
     *             》第一层循环控制的是位数,比如第一轮是个位数,第二轮是十位数,依次类推
     *             第二层有循环有两个循环:
     *                 》第二层的第一个循环就是根据元素在指定位数的值放到对应的二维数组中,也顺便要记录下元素在everyBucketNum的数量
     *                 》第二层的第二个循环是根据everyBucketNum,按照顺序取出二维数组的元素到待排序的数组中,记住还得把
     *             everyBucketNum置为null,因为下一轮的位数得使用。
     * 
     *         
     * 
     */
    private static void radixSort(int[] arr) {
        int maxNum = arr[0];
        //确定arr中最大的数
        for(int i=1;i<arr.length;i++) {
            if(maxNum < arr[i]) {
                maxNum = arr[i];
            }
        }
        
        int maxLength = (maxNum+"").length();    //得到最大数的长度
        int[][] bucket = new int[10][arr.length];    //二维空桶;我解释下为什么bucket不需要在每轮之后重新设置或者重新new一个:
                                                    //等全部结束后,你去遍历二维数组会发现里面有出现多个重复的数,但是你会发现
                                                    //一个神奇的事是原数组真的顺序排好了,不会受到二维数组中其他重复的元素的影响,
                                                    //那是因为everyBucketNum记录了二维数组哪个位置有元素并且数量是多少,这样就不会去遍历重复无用的元素
        int[] everyBucketNum = new int[10];    //长度定义为10是因为不管什么位数上的都是0-9
        
        //两层循环
        for(int j=0,n=1;j<maxLength;j++,n*=10) {    //控制位数的轮数
            for(int k=0;k<arr.length;k++) {    
                //得到元素的指定位数的数
                int digit = (arr[k]/n)%10;    //这个除n后会把我们的相要的位数变成个位数,然后再%10就能拿到了
                
                bucket[digit][everyBucketNum[digit]] = arr[k];    //将元素放到桶中
                
                everyBucketNum[digit]++;    //添加到桶中也需要在一维数组记录元素的个数
            }
            
            int index = 0;
            for(int t=0;t<everyBucketNum.length;t++) {    //把二维数组的元素依次加入到原生数组中
                if(everyBucketNum[t] !=0 ) {    //当everyBucketNum[t]不为0,就可以确定t位置有元素。
                    for(int m=0;m<everyBucketNum[t];m++)    //比如说某个位置出现了2个元素,那么就要遍历2次
                        arr[index++] = bucket[t][m];
                }
                everyBucketNum[t]=0;    //放回原数组后,需要将everyBucketNum置为0,方便下一轮使用
            }
            
        }
        
    }

 

posted @ 2020-11-21 16:43  爱编程DE文兄  阅读(244)  评论(0编辑  收藏  举报