要点:按照位数排序,从个位数开始,位数不够则补零,将数字放置在其位数相对应的桶中,然后再从桶中依次取出排序,如此循环直到最高位,循环次数由数组中最大的绝对值的位数决定。
package DataStructure;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class RadixSort {
public static void main(String[] args) {
// int[] arr = {55, 48, 0, 24, -88, 120, 558, -1, 1256, 26842};
// sort3(arr);
// System.out.println(Arrays.toString(arr));
int[] arr = new int[8000000];
for (int i = 0; i < 8000000; i++) {
arr[i] = (int) (Math.random() * 800000); // 即[0,1) * 800000
}
sort(arr); // 8000000个数据,使用ArrayList耗时约5秒
sort2(arr); // 8000000个数据,使用二维数组耗时约2秒
}
// 使用ArrayList代替二维数组
public static void sort (int[] arr) {
ArrayList<Integer>[] bucket = new ArrayList[10];
for (int i = 0; i < 10; i++) {
bucket[i] = new ArrayList<>(arr.length);
}
// 获取最大值的位数
int maxLength = (getMax(arr) + "").length();
// 从个位开始循环,将数值放入与位数相对应的桶中
for (int i = 0; i < maxLength; i++) {
for (int num : arr) {
int j = (num / (int)Math.pow(10, i)) % 10;
bucket[j].add(num);
}
for (int k = 0, s = 0; k < 10; k++) {
for (int l = 0; l < bucket[k].size(); l++) {
arr[s++] = bucket[k].get(l);
}
// 添加完数据后,务必要清空每一个桶。
bucket[k].clear();
}
}
}
// 使用二维数组
public static void sort2 (int[] arr) {
// 十个桶,每个桶的长度为数组元素个数。
int[][] bucket = new int[10][arr.length];
// 获取最大值的位数
int maxLength = (getMax(arr) + "").length();
// 创建一个数组,用于记录每一个桶中添加的元素个数:
int[] valueNum = new int[10];
// 从个位开始循环,将数值放入与位数相对应的桶中
for (int i = 0; i < maxLength; i++) {
for (int num : arr) {
int j = (num / (int)Math.pow(10, i)) % 10;
// j表示第j个桶,valueNum[j]表示第j个桶的元素个数,添加到桶后,valueNum[j]++
bucket[j][valueNum[j]++] = num;
}
// 遍历每个桶,将元素依次添加到原数组中:
for (int k = 0, s = 0; k < 10; k++) {
if (valueNum[k] != 0) {
for (int l = 0; l < valueNum[k]; l++) {
arr[s++] = bucket[k][l];
}
// 添加完后,务必将桶清零
valueNum[k] = 0;
}
}
}
}
// 考虑负数
public static void sort3 (int[] arr) {
// 二十个桶,0~9负数,10~19正数,每个桶的长度为数组元素个数。
int[][] bucket = new int[20][arr.length];
// 获取最大绝对值的位数
int maxLength = (getAbsMax(arr) + "").length();
// 创建一个数组,用于记录每一个桶中添加的元素个数:
int[] valueNum = new int[20];
// 从个位开始循环,将数值放入与位数相对应的桶中
for (int i = 0; i < maxLength; i++) {
for (int num : arr) {
int j = (num / (int)Math.pow(10, i)) % 10;
// num为负数时加到0~9桶,num为正数时加到10~19桶。
if (num < 0) {
bucket[j + 9][valueNum[j + 9]++] = num;
}else {
bucket[j + 10][valueNum[j + 10]++] = num;
}
}
// 遍历每个桶,将元素依次添加到原数组中:
for (int k = 0, s = 0; k < 20; k++) {
if (valueNum[k] != 0) {
for (int l = 0; l < valueNum[k]; l++) {
arr[s++] = bucket[k][l];
}
// 添加完后,务必将桶清零
valueNum[k] = 0;
}
}
}
}
// 获取数组中的最大值
public static int getMax(int[] arr) {
int max = arr[0];
for (int value : arr) {
if (value > max) {
max = value;
}
}
return max;
}
// 获取数组中的绝对值最大值
public static int getAbsMax(int[] arr) {
int max = Math.abs(arr[0]);
for (int value : arr) {
int absValue = Math.abs(value);
if (absValue > max) {
max = absValue;
}
}
return max;
}
}