java 数组负数排序_Java实现基数排序(可支持负数)

最近在折腾排序算法,发现网上对基数排序大多数都是对正整数的总结,很少讲负数。查看资料,发现有两种方式可以简单的解决负数问题:

方式一:查找需要排序的数组最小值,如果最小值为负数,则数组中的所有元素减轻最小值,使得数组中不出现负数。(本文基于此方式实现)

方式二:将桶的大小从10扩大为20,负数从小到大在 0-9 号桶,正数从小到大在 10 - 19 号桶,具体代码实现可查看(juejin.im/post/684490…)。

1、简介

基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部分资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序。

2、基本思想

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

3、图解

3.1 动态演示

28f2c567af53535e83156d09eeed9ab5.gif

3.2 有负数的情况下的图文说明

35694b51405faa50e316546f937bf88b.png

4、代码示例

public class RadixSort {

public static void main(String[] args) {

int[] arr = {-99, 53, -3, 542, 748, -48, 14, 214, -23, -56};

radixSort(arr);

System.out.println(Arrays.toString(arr));

}

public static void radixSort(int[] arr) {

int maxValue = arr[0];

int minValue = arr[0];

for (int i = 1; i < arr.length; i++) {

maxValue = Math.max(maxValue, arr[i]);

minValue = Math.min(minValue, arr[i]);

}

// 如果最小值为负数,则数组中的数全部减去最小值,这样能保证数组中最小数是0

if (minValue < 0) {

for (int i = 0; i < arr.length; i++) {

arr[i] -= minValue;

}

// 最大值也需要减,不然可能出现位数发生变化

maxValue -= minValue;

}

int length = String.valueOf(maxValue).length();

// 表示10个桶

int[][] bucket = new int[10][arr.length];

// 记录每个桶实际存放几个数据,比如:bucketElementCount[0]记录着bucket[0]桶放入数据个数

int[] bucketElementCount = new int[10];

for (int i = 0, j = 1; i < length; i++, j *= 10) {

for (int k = 0; k < arr.length; k++) {

int element = arr[k] / j % 10;

bucket[element][bucketElementCount[element]] = arr[k];

bucketElementCount[element]++;

}

int index = 0;

// 遍历每个桶的数量,放入原数组

for (int n = 0; n < bucketElementCount.length; n++) {

if (bucketElementCount[n] != 0) {

for (int t = 0; t < bucketElementCount[n]; t++) {

arr[index++] = bucket[n][t];

}

}

// 需要把bucketElementCount置为0,不然会出错

bucketElementCount[n] = 0;

}

}

if (minValue < 0) {

for (int i = 0; i < arr.length; i++) {

arr[i] += minValue;

}

}

}

}

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值