基数排序

一.基数排序介绍

基数排序(radix sort)的思想是多关键字排序,属于分配式排序,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,然后依次收集各个桶内数据,通过分配和收集达到排序的目的

基数排序是1887年赫尔曼·何乐礼发明的,它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较

基数排序示意图
在这里插入图片描述

二.执行流程

通过一个例子来介绍基数排序过程

原始序列:80, 43, 155, 987, 100, 31, 6, 299, 155, 0

1.初始桶

每个关键字的每一位都是由“数字”组成的,数字的范围是0~9,所以准备10个桶用来放关键字,这里所说的“桶”,其实是一个先进先出的队列(从桶的上面进,下面出)
在这里插入图片描述

2.按照个位分配排序

80的最低位是0放入桶0、43最低位是3放入桶3、155最低位是5放入桶5…以此类推,第一趟分配结果如下:
在这里插入图片描述

收集过程是这样的:按桶0到桶9的顺序收集,注意关键字从桶的下面出
桶0:80,100,0
桶1:31
桶2:没有关键字不收集
.
.
.
桶9:299
将每桶收集的关键字依次排开,所以第一趟收集后的结果为:
80,100,0,31,43,155,155,6,987,299
注意观察,最低位有序了,这就是第一趟基数排序后的结果

3.在第一趟排序结果的基础上,按照十位进行分配

80的十位是8放入桶8、100的十位是0放入桶0、0的十位是0放入桶0…以此类推,第二趟分配结果如下图:
在这里插入图片描述
依次收集各个桶内数据结果如下:
100,000,006,031,043,155,155,080,987,299
注意观察,十位也已经有序了,这就是第二趟基数排序后的结果(为了方便观察,数字补0到同一长度)

4.在第二趟的基础上进行第三趟分配收集(到了最高位,百位,也是最后一趟)

100的百位是1放入桶1、000的百位是0放入桶0、006的百位是0放入桶0…以此类推,第三趟分配结果如下图:
在这里插入图片描述
依次收集各个桶内数据结果如下:
0,6,31,43,80,100,155,155,299,987

现在最高位有序,最高位相同的关键字按中间位有序,中间位相同的关键字按最低位有序,于是整个序列有序,基数排序过程结束

三.代码实现思路

1.定义一个要排序的数组为初始数组

2.定义一个二维数组,即0~9共10个桶,每个桶是一个一维数组,每个一维数组的长度为初始数组的长度

3.定义一个一维数组,用来存储每个桶中数据的个数,由于这个一维数组就是一个桶,所以它的长度为10

4.找到数组中最大的数据,并计算出这个最大值的位数,最大值有几位,循环就进行几次

5.根据最大值的位数开始循环,按照个十百…的顺序依次进行排序

5.1首先取出个位上的数字

5.2把个位上数字对应的数放入对应的桶中

5.3.把全部数据放入完毕后,按照桶0~9的顺序,先进先出的取出并覆盖到初始数组中,注意这里要判断一下,桶中有数据才取

5.4覆盖完毕后,对每一个桶进行清零操作以便下一次循环

四.代码实现

/**
 * 基数排序
 */
public class RadixSort {
    public static void main(String[] args) {
        //定义要排序的数组
//        int[] arr = new int[]{34, 512, 36, 67, 89, 6};
        int[] arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 1000);
        }
        System.out.println("初始数组为:" + Arrays.toString(arr));

        //定义二维数组,即0-9共10个桶,每个桶是一个一维数组,这个桶其实就是一个先进先出的队列
        int[][] bucket = new int[10][arr.length];

        //定义一个一维数组,用来存储每个桶中放入的数字数量
        //bucketElementCount[0]即为第一个桶,bucketElementCount[1]即为第二个桶,以此类推...
        int[] bucketElementCount = new int[10];

        //找出数组中的最大值
        //假设第一个数就是最大值
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }

        //求这个最大值有几位
        int maxDigit = (max + "").length();

        //定义一个变量用来取出数字的个十百位等
        int n = 1;

        //开始循环,最大值有几位就循环几次
        for (int i = 0; i < maxDigit; i++, n *= 10) {
            //按照个十百...的顺序依次比对,即第一次循环按照个位比较,第二次循环按照十位比较...

            //定义一个变量用来表示要排序数组的下标
            int index = 0;

            for (int j = 0; j < arr.length; j++) {
                //循环取出数字的个十百位等
                int digit = arr[j] / n % 10;
                //将数组中的数字放入到与其对应的桶中
                bucket[digit][bucketElementCount[digit]] = arr[j];
                //桶中放入数字后,数字的数量需要加1
                bucketElementCount[digit]++;
            }
            //按0-9的顺序从桶中先进先出的取出数据覆盖到原数组
            for (int k = 0; k < bucketElementCount.length; k++) {
                //判断桶中是否有数据,有数据才取出
                if (bucketElementCount[k] != 0) {
                    //代码走到这里说明桶中有数据
                    for (int l = 0; l < bucketElementCount[k]; l++) {
                        //将桶中的数据覆盖到原数组中
                        arr[index] = bucket[k][l];
                        index++;
                    }
                }
                //每一轮需要把桶中的数据清零以便下一轮继续存储
                bucketElementCount[k] = 0;
            }
            System.out.println("第" + (i + 1) + "轮排序为:" + Arrays.toString(arr));
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值