最近在折腾排序算法,发现网上对基数排序大多数都是对正整数的总结,很少讲负数。查看资料,发现有两种方式可以简单的解决负数问题:
方式一:查找需要排序的数组最小值,如果最小值为负数,则数组中的所有元素减轻最小值,使得数组中不出现负数。(本文基于此方式实现)
方式二:将桶的大小从10扩大为20,负数从小到大在 0-9 号桶,正数从小到大在 10 - 19 号桶,具体代码实现可查看(juejin.im/post/684490…)。
1、简介
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部分资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序。
2、基本思想
将所有待比较数值统一为同样的数位长度,数位较短的的数前面补零。然后,从低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
3、图解
3.1 动态演示
3.2 有负数的情况下的图文说明
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;
}
}
}
}
复制代码