文章目录
- 基数排序
- 一、基数排序
- 概念
- 1.LSD排序法(最低位优先法)
- 2.MSD排序法(最高位优先法)
基数排序
一、基数排序
概念
-
基数排序是一种非比较型整数排序算法
-
将整数按位数切割成不同的数字,然后按每个位数分别比较
-
使用场景:按位分割进行排序,适用于大数据范围排序,打破了计数排序的限制
-
稳定性:稳定
-
按位分割技巧:arr[i] / digit % 10,其中digit为10^n。
1.LSD排序法(最低位优先法)
-
从最低位向最高位依次按位进行计数排序。
-
进出的次数和最大值的位数有关
-
桶可以用队列来表示
-
数组的每个元素都是队列
- 1.先遍历找到最大值
- 2.求出最高位
public static void radixSortR(int[] array) {
//10进制数,有10个桶,每个桶最多存array.length个数
int[][] bucket = new int[10][array.length];
//桶里面要存的具体数值
int[] bucketElementCounts = new int[10];
//用来计算,统计每个桶所存的元素的个数,每个桶对应一个元素
//1.求出最大数
int MAX = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > MAX) {
MAX = array[i];
}
}
//求最大值的位数,先变成字符串,求字符串长度
int MAXCount = (MAX + "").length();
//最大位数的个数,进行几次计数排序
for (int i = 0; i < MAXCount; i++) {//i代表第几次排序
//放进桶中
for (int k = 0; k < array.length; k++) {
//k相当于遍历待排数值
//array[k] /(int) Math.pow(10, i)%10 求出每次要比较位的数
//求的是个位,并且是对应趟数的个位
int value = (array[k] / (int) Math.pow(10, i)) % 10;
//根据求出的位数,找到对应桶,放到对应桶的位置
bucket[value][bucketElementCounts[value]] = array[k];
//不管value 为多少,bucketElementCounts[value]的值都为0
//相当于存到对应桶的0位bucket[value][0]
bucketElementCounts[value]++; //从0->1
//对应桶的技术数组开始计数
}
//取出每个桶中的元素,赋值给数组
int index = 0;//array新的下标
for (int k = 0; k < bucketElementCounts.length; k++) {//遍历每个桶
if (bucketElementCounts[k] != 0) {//桶里有元素
for (int j = 0; j < bucketElementCounts[k]; j++) {//比那里每个桶的元素
array[index] = bucket[k][j];
index++;
}
}
bucketElementCounts[k] =0;//每个桶遍历完后,清空每个桶的元素;
}
}
}
2.MSD排序法(最高位优先法)
- 从最高位向最低位依次按位进行排序。
- 按位递归分组收集
- 1.查询最大值,获取最高位的基数
- 2.按位分组,存入桶中
- 3.组内元素数量>1,下一位递归分组
- 4.组内元素数量=1.收集元素
/**
* 基数排序--MSD--递归
* @param array
*/
public static void radixSortMSD(int[] array) {
//1.求出最大数
int MAX = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > MAX) {
MAX = array[i];
}
}
//求最大值的位数,先变成字符串,求字符串长度
int MAXCount = (MAX + "").length();
// 计算最大值的基数
int radix = new Double(Math.pow(10, MAXCount - 1)).intValue();
int[] arr = msdSort(array, radix);
System.out.println(Arrays.toString(arr));
}
public static int[] msdSort(int[] arr, int radix){
// 递归分组到个位,退出
if (radix <= 0) {
return arr;
}
// 分组计数器
int[] groupCounter = new int[10];
// 分组桶
int[][] groupBucket = new int[10][arr.length];
for (int i = 0; i < arr.length; i++) {
// 找分组桶位置
int position = arr[i] / radix % 10;
// 将元素存入分组
groupBucket[position][groupCounter[position]] = arr[i];
// 当前分组计数加1
groupCounter[position]++;
}
int index = 0;
int[] sortArr = new int[arr.length];
// 遍历分组计数器
for (int i = 0; i < groupCounter.length; i++) {
// 组内元素数量>1,递归分组
if (groupCounter[i] > 1) {
int[] copyArr = Arrays.copyOf(groupBucket[i], groupCounter[i]);
// 递归分组
int[] tmp = msdSort(copyArr, radix / 10);
// 收集递归分组后的元素
for (int j = 0; j < tmp.length; j++) {
sortArr[index++] = tmp[j];
}
} else if (groupCounter[i] == 1) {
// 收集组内元素数量=1的元素
sortArr[index++] = groupBucket[i][0];
}
}
return sortArr;
}
点击移步博客主页,欢迎光临~