• 基数排序.


    基数排序(桶排序)介绍:

    1)基数排序(radixsort)属于"分配式排序"(distribution sort),又称"桶子法"(bucket sort)或 bin sort,顾名思义,它是通过关键值的各个位的值,将要排序的元素分配至某些"桶"中,达到排序的作用.
    2.基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法
    3.基数排序(Radix Sort)是桶排序的扩展
    4,基数排序是1887年赫尔曼,何乐礼发明的,他是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较.

    基数排序的基本思想

    1,将所有带比较数值同样为同样的数位长度,数位较短的数前面补零,然后,从最低位开始,依次进行排序,这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列.

    图文解释

    将数组{53,3,542,748,14,214}使用基数排序,进行升序排序

    • 数组的初始状态{53,3,542,748,14,214}
    • 第一轮排序:
      • 将每个原始的个位取出,然后看这个数应该放在哪个对应的桶(一个一位数组)
      • 按照这个桶的顺序(一维数组的下标)依次取出数据,放入到原来的数组.
      • 数组第一轮排序arr={542,53,3,14,214,748}
        *在这里插入图片描述
      • 第二轮排序
      • 将每个元素的十位取出,然后看这个数应该放在哪个对应的桶(一个以维数组)
      • 按照这个桶的顺序(一维数组的下标)依次取出数据,在重写放回arr
      • 第二轮排序结果{3,14,214,542,748,53}在这里插入图片描述
    • 第三轮排序
      • 将每个元素的百位取出,然后看这个数应该放在哪个对应的桶(一个以维数组)
      • 按照这个桶的顺序(一维数组的下标)依次取出数据,在重写放回arr
      • 第三轮的排序结果{3,14,53,214,542,748}
        在这里插入图片描述

    代码实现

    排序的次数:我们总共排序多少轮,我们看的是最大的数有多少位-1位,最大的位数是1234,那么排序三次,是321123那么排序5次数

    代码逐步求解过程
    package sort;
    
    import java.util.Arrays;
    
    public class RadixSort {
        public static void main(String[] args) {
            int[] arr={53,3,542,748,14,214};
            radixSort(arr);
        }
    
        //基数排序方法
        public static void radixSort(int[] arr){
            //第一轮(针对每个原始的个位进行排序处理
    
    
    
            // 定义一个二维数组,表示十个桶,每个桶就是一个以维数组
            //说明一把,这个二维数组包含十个一维数组,
            //为了防止在放入数的时候,数据溢出,则每个以为数组(桶),大小定位arr.length空间换时间)
            //很明确,基数排序是空间换时间的金典算法
            int[][] bucket =new int[10][arr.length];
    
            //为了记录每个桶中实际存放了多少数据,我们定义一个一维数组来记录各个桶每次放入的数据个数
            //可以这样理解
            //bucketElementCounts[0]记录的就是bucket[0]桶放入数据的个数
            int[] bucketElementCounts=new int[10];
    
    
            //第一轮(针对每个原始的个位进行排序处理)
            for (int j=0;j<arr.length;j++){
                //取出每个元素的个位
                int digitOfElement=arr[j]%10;
                //放入到对应的桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j];
                //这里为什么++,以内万一这个桶还有其他元素放进来,不能让他覆盖,而后放到下一位.
                bucketElementCounts[digitOfElement]++;
            }
    
            //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来的数组)
            int index=0;
            //遍历每一个桶,并将桶中的数据,放入到原数组
            for(int k=0;k<bucketElementCounts.length;k++){
                //如果桶中有数据,我们才放入到原来的数组
                if(bucketElementCounts[k]!=0){
                    //循环该桶即第k个桶(即第k个一位数组),放入
                    for(int l=0;l<bucketElementCounts[k];l++){
                        //取出元素放入到arr
                        arr[index++]=bucket[k][l];
    
                    }
                }
                //第一轮以后我们的桶中的数量清零,即每个bucketElementCounts[k]=0;
                bucketElementCounts[k]=0;
            }
            System.out.println("第一轮结果对个位的排序处理以后:"+ Arrays.toString(arr));
    
     //========================================================
            //第二轮(针对每个原始的个十位进行排序处理)
            for (int j=0;j<arr.length;j++){
                //取出每个元素的个位
                int digitOfElement=arr[j]/10%10;
                //放入到对应的桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j];
                //这里为什么++,以内万一这个桶还有其他元素放进来,不能让他覆盖,而后放到下一位.
                bucketElementCounts[digitOfElement]++;
            }
    
            //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来的数组)
             index=0;
            //遍历每一个桶,并将桶中的数据,放入到原数组
            for(int k=0;k<bucketElementCounts.length;k++){
                //如果桶中有数据,我们才放入到原来的数组
                if(bucketElementCounts[k]!=0){
                    //循环该桶即第k个桶(即第k个一位数组),放入
                    for(int l=0;l<bucketElementCounts[k];l++){
                        //取出元素放入到arr
                        arr[index]=bucket[k][l];
                        index++;
    
                    }
                }
                //第二轮以后我们的桶中的数量清零,即每个bucketElementCounts[k]=0;
                bucketElementCounts[k]=0;
            }
            System.out.println("第二轮结果对个位的排序处理以后:"+ Arrays.toString(arr));
    
    
            //====================================================
            //第三轮(针对每个原始的百位进行排序处理)
            for (int j=0;j<arr.length;j++){
                //取出每个元素的个位
                int digitOfElement=arr[j]/100%10;
                //放入到对应的桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j];
                //这里为什么++,以内万一这个桶还有其他元素放进来,不能让他覆盖,而后放到下一位.
                bucketElementCounts[digitOfElement]++;
            }
    
            //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来的数组)
            index=0;
            //遍历每一个桶,并将桶中的数据,放入到原数组
            for(int k=0;k<bucketElementCounts.length;k++){
                //如果桶中有数据,我们才放入到原来的数组
                if(bucketElementCounts[k]!=0){
                    //循环该桶即第k个桶(即第k个一位数组),放入
                    for(int l=0;l<bucketElementCounts[k];l++){
                        //取出元素放入到arr
                        arr[index]=bucket[k][l];
                        index++;
    
                    }
                }
                //第二轮以后我们的桶中的数量清零,即每个bucketElementCounts[k]=0;
                bucketElementCounts[k]=0;
            }
            System.out.println("第三轮结果对个位的排序处理以后:"+ Arrays.toString(arr));
    
        }
    
    
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    RadixSort

    package sort;
    
    import java.util.Arrays;
    
    public class RadixSort {
        public static void main(String[] args) {
            int[] arr={53,3,542,748,14,214};
            radixSort(arr);
              //基数排序的速度测试,可以试试8000000,我们可以看出内存不足,典型的空间换时间.
            int[] arr2=new int[800000];
            for (int i=0;i<800000;i++){
                arr2[i]=(int)(Math.random()*400000);//生成一个[0,20000)的随机整数
            }
            long startTime=System.currentTimeMillis();
            radixSort(arr2);
            long endTime=System.currentTimeMillis();
            System.out.println("排序用的时间:"+(endTime-startTime));
    
        }
    
        //基数排序方法
        public static void radixSort(int[] arr){
            //根据推到过程,我们可以得到基数排序的代码
            //先得到数组中最大数的位数
            int max=arr[0];//假设第一个数就是最大数
            for(int i=0;i<arr.length;i++){
                if(arr[i]>max){
                    max=arr[i];
                }
            }
            //得到最大位是几位数
            int maxLength=(max+"").length();
    
            // 定义一个二维数组,表示十个桶,每个桶就是一个以维数组
            //说明一把,这个二维数组包含十个一维数组,
            //为了防止在放入数的时候,数据溢出,则每个以为数组(桶),大小定位arr.length空间换时间)
            //很明确,基数排序是空间换时间的金典算法
            int[][] bucket =new int[10][arr.length];
    
            //为了记录每个桶中实际存放了多少数据,我们定义一个一维数组来记录各个桶每次放入的数据个数
            //可以这样理解
            //bucketElementCounts[0]记录的就是bucket[0]桶放入数据的个数
            int[] bucketElementCounts=new int[10];
    
            //这里我们使用循环将代码处理
            for(int i=0,n=1;i<maxLength;i++,n*=10){
                //针对每个元素对应的为排序(第一次是个位,第二次是十位,一次类推
                // )
                for (int j=0;j<arr.length;j++){
                    //取出每个元素的个位
                    int digitOfElement=arr[j]/n%10;
                    //放入到对应的桶中
                    bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j];
                    //这里为什么++,以内万一这个桶还有其他元素放进来,不能让他覆盖,而后放到下一位.
                    bucketElementCounts[digitOfElement]++;
                }
    
                //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来的数组)
                int index=0;
                //遍历每一个桶,并将桶中的数据,放入到原数组
                for(int k=0;k<bucketElementCounts.length;k++){
                    //如果桶中有数据,我们才放入到原来的数组
                    if(bucketElementCounts[k]!=0){
                        //循环该桶即第k个桶(即第k个一位数组),放入
                        for(int l=0;l<bucketElementCounts[k];l++){
                            //取出元素放入到arr
                            arr[index++]=bucket[k][l];
    
                        }
                    }
                    //第i轮以后我们的桶中的数量清零,即每个bucketElementCounts[k]=0;
                    bucketElementCounts[k]=0;
                }
                System.out.println("第"+(i+1)+"轮排序处理以后:"+ Arrays.toString(arr));
    
            }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    基数排序是一个典型的空间换时间的案例.我们我们对8000000万个数据进行排序,

    基数排序的说

    1.基数排序是对传统桶排序的扩展,速度很快
    2,基数排序是经典的空间换时间的方式,占用内存很大,当对海量的数据进行排序时,容易造成OutOfMemorError错误.
    3,基数排序时稳定[注:假定在待排序的记录列中,存在多个具有相同的关键字的记录,若进过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而且排序后的序列中,r[i]仍在r[j]之前],则成为这种排序算法是稳定的,否则称为不稳定的
    4.有负数的数组中,我们不用基数排序来进行排序,如果支持负数,参考:https;//code.i-harness.com/zh-CN/q/e98fa9

  • 相关阅读:
    Maven的常用命令
    day2_QT
    Kafka中遇到的错误:
    Python机器学习实战-特征重要性分析方法(1):排列重要性(附源码和实现效果)
    js 去除字符串空格
    Linux 安装jenkins
    【java表达式引擎】一、汇总目前开源的公式计算开源库
    js之页面列表加载常用方法总结
    vue生成svg二维码
    探索服务器的无限潜能:创意项目、在线社区与更多可能
  • 原文地址:https://blog.csdn.net/weixin_51599093/article/details/127741239