基数排序详解

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

  1. 基数排序 vs 计数排序 vs 桶排序
    基数排序有两种方法:

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

  • 基数排序:根据键值的每位数字来分配桶;
  • 计数排序:每个桶只存储单一键值;
  • 桶排序:每个桶存储一定范围的数值;
import java.util.Arrays;

/**
 * @Version :
 * @Description : 计数排序
 */
public class RadioSort {

    public static void main(String[] args) {
        int arr[]={3,2,2,5,4,0,5,4,5,1, 48, 96, -148, -136, -129};
//        int arr[]={48, 96, -148, -136, -129};
        int[] copy = Arrays.copyOf(arr, arr.length);
        int max = getMaxValue(arr);
        int maxdigit = getLength(max);
        copy = radioSort(copy, maxdigit);
        for (int i : copy) {
            System.out.print(i + " ");
        }
    }

    // 获取最大值
    public static int getMaxValue(int[] arr) {
        int max = arr[0];
        for (int value : arr) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    // 获取最大值长度
    public static int getLength(int value) {
        if (value == 0 ){
            return 1;
        }
        int count = 0;
        while (value != 0) {
            count++;
            value = value / 10;
        }
        return count;
    }

    public static int[] radioSort(int[] arr, int maxdigit) {
        int mod = 10;  // 取商
        int dev = 1;   // 取余数
        for (int i = 0; i < maxdigit; i++, mod *= 10, dev *= 10) {
            // 20个长度[0-9]对应负数,[10-19]对应正数 ,已经够装了,不需要再 int[mod * 2][0]
            int[][] buckets = new int[20][0];
            for (int j = 0; j < arr.length; j++) {
                /**
                 * 考虑负数的情况,这里扩展一倍队列数,其中 [0-9]对应负数,[10-19]对应正数 (bucket + 10)
                 * 例如 : 48   96  -148  -136  -129
                 *        _   _   _   _   _   _   _        _       _   _    _     _    _    _       _    _    _    _    _   _
                 *        0   1   2   3   4   5   6        7       8   9   10    11   12   13      14   15   16   17   18  19
                 * 第一次:   -129 -148   -136(-6+10=4)                                                       96       48
                 * 弹出:    -129  -148   -136                                                                96        48
                 * 第二次:                       -148(6) -136(7)  -129(-129%100=-29/10 =-2+10=8)    48                      96
                 * 弹出:                        -148     -136     -129                             48                      96
                 *
                 *                                                -129    96(0+10)
                 *                                                -136    48
                 * 第三次:                                         -148(-1+10=9)
                 */
                int index = (arr[j] % mod) / dev + 10;
//                System.out.println("index:" + index + " mod: " + mod + " dev " + dev);
                buckets[index] = appendA(buckets[index], arr[j]);
             }

            // 重新入桶
            int sortedIndex = 0;
            for (int[] bucket : buckets) {
                for (int value : bucket) {
                    arr[sortedIndex++] = value;
                }
            }
        }
        return arr;

    }

    public static int[] appendA(int[] arr, int value) {
        // 复制数组可以增加数组的长度
        arr = Arrays.copyOf(arr, arr.length + 1);
        arr[arr.length - 1] = value;
        return arr;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值