本文我准备用Java实现基数排序。基数排序由于其独有的排序方式,只适合待排序的数字都是非负整数的情况。基数排序和计数排序名字很相像,不要搞混淆了。接下来我列举一下二者的共同点和不同点:
计数排序和基数排序的共同点:
1、都是只适合对非负整数的排序
2、都是线性的时间复杂度
计数排序和基数排序的区别:
1、计数排序不能接受有很大值的待排序元素;而基数排序可以接受
2、计数排序实现和操作简单,只需要额外的一个数组(最大值大了,这个空间就大了);而基数排序还要算待排序数字的每一位,还要辅以10个桶的额外空间
具体的排序算法过程已经在注释里面了,大家可以复制代码到IDE里面,用DEBUG模式研究算法的过程:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* @author LiYang
* @ClassName RadixSort
* @Description 基数排序算法
* @date 2019/11/5 16:45
*/
public class RadixSort {
/**
* 基数排序算法(RadixSort)
* 基数排序,需要排序元素是非负整数
* @param arr 待排序数组
*/
public static void radixSort(int[] arr){
//先求出所有元素的最大位数
int maxDigit = 0;
//遍历待排序数组
for (int i = 0; i < arr.length; i++) {
//遍历比较,得到最大整数位数
maxDigit = Math.max(maxDigit, (int)Math.ceil(Math.log10(arr[i])));
}
//查看本次待排序数组的最大整数的位数
//System.out.println("最大整数位:" + maxDigit);
//用于基数排序的桶,容量为10,也就是数字位0-9
List[] bucket = new ArrayList[10];
//初始化桶:List[] bucket
for (int i = 0; i < bucket.length; i++) {
bucket[i] = new ArrayList();
}
//从个位开始,一位一位地往高位进行基数排序
for (int digit = 1; digit <= maxDigit; digit++) {
//将每一个待排序元素,取当前数位,进入对应下标的桶
for (int i = 0; i < arr.length; i++) {
//得到元素当前数位的数字
int radix = arr[i] / (int)Math.pow(10, (digit - 1)) % 10;
//装入对应下标的桶
bucket[radix].add(arr[i]);
}
/*
* 当前数位的基数排序后,重新按照0-9号桶的顺序遍历
* 遍历中的每个桶按从左到右的顺序重新放入原数组
* 也就是每个桶的ArrayList从下标0开始,到size-1
*/
//记录arr的下标值
int index = 0;
//遍历每个桶,从0号桶到9号桶
for (int i = 0; i < bucket.length; i++) {
//每个桶从左到右遍历元素
for (int j = 0; j < bucket[i].size(); j++) {
//0-9号桶,每桶从左到右,依次赋值回原数组进行记录
//以便于下一次基数排序,提供中间排序的序列
arr[index++] = (int)bucket[i].get(j);
}
}
//当前基数排序结束,清空所有桶,以便于下一次基数排序
for (int i = 0; i < bucket.length; i++) {
//清空所有桶
bucket[i].clear();
}
}
}
/**
* 验证基数排序算法
* @param args
*/
public static void main(String[] args) {
//待排序数组
int[] arr = new int[30];
//随机数类
Random random = new Random();
//随机生成排序数组(1000以内的整数)
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(1000);
}
//打印待排序数组
System.out.println("基数排序前:" + Arrays.toString(arr));
//进行基数排序
radixSort(arr);
//打印基数排序后的数组
System.out.println("基数排序后:" + Arrays.toString(arr));
}
}
运行 RadixSort 类的main方法,基数排序算法测试通过:
基数排序前:[329, 695, 789, 151, 103, 311, 339, 566, 680, 353, 652, 222, 911, 385, 556, 444, 575, 108, 75, 998, 649, 398, 358, 26, 568, 954, 383, 24, 6, 701]
基数排序后:[6, 24, 26, 75, 103, 108, 151, 222, 311, 329, 339, 353, 358, 383, 385, 398, 444, 556, 566, 568, 575, 649, 652, 680, 695, 701, 789, 911, 954, 998]