排序算法-基数排序:算法难理解?执行过程打印出来一步一步看

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成0-9的数字,然后按每个位的数分别进行桶排序。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

基数排序具体步骤如下:

1、确定最大数的位数(考虑负数);

2、按位循环进行桶排序。

注:桶排序参考上篇文章;由于每位仅有0-9是个数,考虑负数情况,桶的数量固定为20,0-9号桶放负数,10-19号桶放不小于0的数。

LSD 基数排序动图演示

执行过程请移步文章末尾:执行过程。

基数排序分为两种方式:LSD(最低位优先(Least Significant Digit first)法)、MSD(最高位优先(Most Significant Digit first)法)。

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

LSD代码实现:

package com.algorithm.sort;

import java.util.Arrays;

/**
 * @author LuoFei
 * @className: RadixSort
 * @projectName algorithm
 * @description: TODO
 * @date 2023/3/3 14:53
 */
public class RadixSort {

    public static void radixSort(int[] arr) {
        System.out.println("获取数组最大数的位数,确定进行几遍桶排序(考虑负数)");
        int maxDigit = getMaxDigit(arr);
        System.out.println("位数为:"+maxDigit);
        sort(arr, maxDigit);
    }

    public static int getMaxDigit(int[] arr) {
        int maxValue = getMaxValue(arr);
        return getNumLength(maxValue);
    }

    public static int getMaxValue(int[] arr) {
        int maxValue = Math.abs(arr[0]);
        for (int value : arr) {
            if (maxValue < Math.abs(value)) {
                maxValue = Math.abs(value);
            }
        }
        return maxValue;
    }

    public static int getNumLength(int value) {
        int num = 0;
        if (value == 0) {
            return 1;
        }
        int temp = value;
        while (temp > 0) {
            temp /= 10;
            num++;
        }
        return num;
    }

    public static void sort(int[] arr, int maxDigit) {
        System.out.println("开始排序");
        System.out.println("通过对数值取余、求商,计算数值每位的十进制数,对每位的十进制数做桶排序。");
        System.out.println("因为是十进制及考虑负数情况,桶的数量定为20,0-9号桶放负数,10-19号桶放不小于0的数");
        int mod = 10;
        int dev = 1;
        System.out.println("定义初始取余基数为:"+mod+", 初始初始为:"+dev);

        for (int i = 0;i<maxDigit;i++,mod*=10,dev*=10) {
            System.out.println("第"+(i+1)+"位开始桶排序");
            int[][] buckets = new int[20][0];
            for(int j=0;j<arr.length;j++) {
                int index = (arr[j]%mod)/dev + 10;
                buckets[index] = arrAppend(buckets[index], arr[j]);
            }

            int index = 0;
            for (int[] bucket : buckets) {
                for (int k = 0;k<bucket.length;k++) {
                    arr[index++] = bucket[k];
                }
            }
            System.out.println("第"+(i+1)+"位桶排序后数组位:"+Arrays.toString(arr));
        }
    }

    public static int[] arrAppend(int[] bucket, int value) {
        bucket = Arrays.copyOf(bucket, bucket.length+1);
        bucket[bucket.length-1] = value;
        return bucket;
    }

    public static void main(String[] args) {
        int[] arr = {65, -122, -58, 30, -19, 21, 2, 34, 42, 7, 2, 0};
        System.out.println("基数排序");
        System.out.println("初始数组:"+ Arrays.toString(arr));
        System.out.println("==============开始基数排序===============");
        radixSort(arr);
        System.out.println("==============基数排序完成===============");
        System.out.println("最终数组"+Arrays.toString(arr));
    }
}

执行过程:

基数排序
初始数组:[65, -122, -58, 30, -19, 21, 2, 34, 42, 7, 2, 0]
==============开始基数排序===============
获取数组最大数的位数,确定进行几遍桶排序(考虑负数)
位数为:3
开始排序
通过对数值取余、求商,计算数值每位的十进制数,对每位的十进制数做桶排序。
因为是十进制及考虑负数情况,桶的数量定为20,0-9号桶放负数,10-19号桶放不小于0的数
定义初始取余基数为:10, 初始初始为:1
第1位开始桶排序
第1位桶排序后数组位:[-19, -58, -122, 30, 0, 21, 2, 42, 2, 34, 65, 7]
第2位开始桶排序
第2位桶排序后数组位:[-58, -122, -19, 0, 2, 2, 7, 21, 30, 34, 42, 65]
第3位开始桶排序
第3位桶排序后数组位:[-122, -58, -19, 0, 2, 2, 7, 21, 30, 34, 42, 65]
==============基数排序完成===============
最终数组[-122, -58, -19, 0, 2, 2, 7, 21, 30, 34, 42, 65]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值