前言
之前说到的排序的时间复杂度都只受限于数组的长度,而不受限与数组元素的大小
今天来讲讲一种以空间换时间的排序算法 —— 箱排序(Bin Sort),及其改良 —— 基数排序(Radix Sort)
为了便于理解,文章中就不引入关于包含负数数组的排序解决方案了,感兴趣的可以看我在github上发布的源码~
手撕算法 - 排序系列
手撕面试题算法<排序>(1)—— 冒泡排序及其优化实现
手撕面试题算法<排序>(2)—— 选择排序
手撕面试题算法<排序>(3)—— 插入排序及其优化实现
手撕面试题算法<排序>(3.5)—— 希尔排序
手撕面试题算法<排序>(4)—— 归并排序
手撕面试题算法<排序>(5)—— 快速排序以及快排为什么快
手撕面试题算法<排序>(6)—— 堆 & 堆排序
手撕面试题算法<排序>(7)—— 箱排序 & 基数排序
源码
看完有收获别忘了点个star哦~
箱排序
箱排序是一种时间复杂度能达到 O(n) 的排序,作为代价,它将会申请待排序数组中最大的数的大小的数组空间,空间复杂度达到 O(arr.maxValue+1),用它来排序大数值数组,是相当浪费空间的做法
思想
箱排序的排序过程无需比对数值,只需要将遍历到的数值放到对应的“箱子”里,最后再统计箱子即可,是一种分配 - 收集的思想
实现
箱排序的实现非常简单,假设待排序数组全为整数:
- 首先遍历待排序数组,得到该数组中的最大值N
- 创建一个长度为N+1的数组bin:
int[] bin = new int[N+1];
- 遍历待排序数组时,遍历到数组元素i,将
bin[i] += 1
- 遍历完毕后,数组
bin
中不为0的位置都为待排序数组中出现过的元素,bin[i]
的值代表i
在待排序数组中出现过几次 - 顺序遍历数组
bin
中不为0的值,令bin[i] -= 1
直到bin[i] == 0
,并将i
顺序装入待排序数组中 - 步骤5的过程相当于从箱子中把值取出
public static void sort(int[] arr) {
// 1. 获取待排序数组中的最大值N
int N = Integer.MIN_VALUE;
for (int val : arr) {
N = Math.max(N, val);
}
// 2. 依据N来构建bin数组
int[] bin = new int[++N];
// 3. 将待排序数组中出现过的值在bin的对应索引处统计
for (int val : arr) {
++bin[val];
}
// 4. 遍历bin数组,获得顺序数组
int idx = 0;
for (int j = 0; j < N; ++j) {