目录
- 一、简介
- 二、代码实现
- 三、应用场景
一、简介
算法 | 平均时间复杂度 | 最好时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 排序方式 | 稳定性 |
---|---|---|---|---|---|---|
基数排序 | O(n*k) | O(n*k) | O(n*k) | O(n+k) | Out-place | 稳定 |
稳定:如果A原本在B前面,而A=B,排序之后A仍然在B的前面;
不稳定:如果A原本在B的前面,而A=B,排序之后A可能会出现在B的后面;
时间复杂度: 描述一个算法执行所耗费的时间;
空间复杂度:描述一个算法执行所需内存的大小;
n:数据规模;
k:“桶”的个数;
In-place:占用常数内存,不占用额外内存;
Out-place:占用额外内存。
基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
图示:
算法步驟:
取得数组中的最大数,并取得位数;
arr为原始数组,从最低位开始取每个位组成radix数组;
对radix进行计数排序(利用计数排序适用于小范围数的特点);
二、代码实现
public class RadixSort {
public static void radixSort(int[] arr) {
if (arr.length < 2)
return;
int maxVal = arr[0];//求出最大值
for (int a : arr) {
if (maxVal < a) {
maxVal = a;
}
}
int n = 1;
while (maxVal / 10 != 0) {//求出最大值位数,即n的迭代次数
maxVal /= 10;
n++;
}
for (int i = 0; i < n; i++) {//迭代n次
List<List<Integer>> radix = new ArrayList<>();
for (int j = 0; j < 10; j++) {
radix.add(new ArrayList<>());//radix包含十个list集合
}
int index;
for (int a : arr) {
index = (a / (int) Math.pow(10, i)) % 10;//这段代码的作用是获取数字 a 的第 i 位数字。
radix.get(index).add(a);//radix根据索引为每个list集合添加元素
}
index = 0;
for (List<Integer> list : radix) {
for (int a : list) {
arr[index++] = a;//赋值到数组中
}
}
}
}
public static void main(String[] args) {
int[] arr = {12, 11, 15, 50, 7, 65, 3, 99, 0};
System.out.println("---排序前: " + Arrays.toString(arr));
radixSort(arr);
System.out.println("基数排序从小到大: " + Arrays.toString(arr));
}
}
三、应用场景
应用场景
:
- 当待排序的数据范围较小,且数据量较大时,基数排序可以是一个很好的选择。
- 基数排序适用于整数、字符串等有限范围内的数据排序,例如手机号码、学号、成绩等。
- 在计算机科学中,基数排序常用于计算机图形学、数据压缩、密码学等领域。
基数排序 vs 计数排序 vs 桶排序
:
这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:
基数排序:根据键值的每位数字来分配桶;
计数排序:每个桶只存储单一键值;
桶排序:每个桶存储一定范围的数值;
参考链接:
十大经典排序算法(Java实现)