1. 计数排序
计数排序实现原理与示例:
2. 代码实现
public class CountingSort {
public static void main(String[] args) {
// 待排序的数组
int[] arr = new int[]{2, 9, 26, 41, 36, 21, 95, 36, 75, 42, 18};
int[] newArr = Arrays.copyOf(arr, arr.length);// 拷贝原数组,用新数组排序,不破坏原数组。非必要
// 排序
countingSort(newArr);
System.out.println(Arrays.toString(newArr));
}
private static void countingSort(int[] arr) {
// 找出数组中最大值
int maxValue = findMaxValue(arr);
// 建立一个以 arr 中最大值 + 1 为数组长度的数组 bucket
int[] bucket = new int[maxValue + 1];// 此时 bucket 数组中元素全为 0
// 遍历 arr,设置 bucket[arr[i]] = bucket[arr[i]] + 1
for (int temp : arr) {
bucket[temp] = bucket[temp] + 1;
}
// 遍历 bucket,依次将元素值不为 0 的数组索引放入 arr 中,并设置 bucket[i] = bucket[i] - 1
int index = 0;
for (int i = 0; i < bucket.length; i++) {
while (bucket[i] > 0) {
arr[index++] = i;
bucket[i] = bucket[i] - 1;
}
}
}
public static int findMaxValue(int[] arr) {
int maxValue = 0;
for (int temp : arr) {
if (temp > maxValue) {
maxValue = temp;
}
}
return maxValue;
}
}
3. 复杂度
时间复杂度:
空间复杂度:
4. 计数排序缺点
- 无法对负整数进行排序。arr 中的元素为 bucket 中的索引,索引不能为负,所以 arr 中不能有负整数。
- 极其浪费内存空间。最小的元素以下的空间都是浪费。
- 当数列最大最小值差距过大时,不适用计数排序。
- 计数排序是一个不稳定的排序。
5. 计数排序优化
对于 arr 中最小元素,新建 bucket 后,bucket[minValue(arr)] 都是浪费的,可以在新建 bucket 时,减少这块空间浪费。
原 bucket:
int[] bucket = new int[maxValue + 1];
优化后 bucket:
int[] bucket = new int[maxValue + 1 - minValue];