Version: Next
计数排序
info
冒泡、选择、插入、归并、快速、希尔、堆排序都是基于 比较 的排序
- 平均时间复杂度最低为 O(nlogn)
计数排序、桶排序、基数排序,都不是基于比较的排序
- 典型的空间换时间,在某些场景下,平均时间复杂度可以比 O(nlogn) 更低
计数排序
- 1954 年由 Harold H. Seward 提出,适合对一定范围内的正数进行排序
- 核心思想:统计每个整数在序列中出现的次数,进而推导出每个整数在
有序序列
中的索引
最简实现
- 用一个数组存储元素出现的次数,数组长度为
元素最大值 + 1
- 数字
1
出现的次数就记录在 数组array[1]
位置- 数字
20
出现的次数就记录在 数组array[20]
位置- 从左向右扫描数组,只要元素有值就输出对应下标,值为几就输出几次
/**
* 计数排序 最简实现
*/
public class CountingSort1 extends Sort<Integer> {
public CountingSort1(Integer[] array) {
this.array = array;
}
@Override
public void sort() {
// 找出元素最大值
int max = array[0];
for (int i = 1; i < array.length; i++)
if (array[i] > max) max = array[i];
// 开辟内存空间,存储每个整数出现的次数
int[] countArray = new int[max + 1];
for (int i = 0; i < array.length; i++)
countArray[array[i]]++;
int current = 0; // 记录当前操作位置的指针
// 遍历表格输出
for (int i = 0; i < countArray.length; i++)
while (countArray[i]-- > 0)
// 直接覆盖 原数组array]
array[current++] = i;
/* current++;
countArray[i]--;*/
}
public static void main(String[] args) {
Integer[] array = {4, 5, 3, 2, 1, 1};
new CountingSort1(array).sort();
for (Integer integer : array) {
System.out.println(integer + " ");
}
}
}
问题
- 无法对负数进行排序
- 极其浪费内存空间
- 不稳定排序
改进
- 从索引
0
开始,依次存放元素出现的次数 - 每个次数累加上前面所有次数,得到的就是元素在有序序列中的位置信息
- 从右向左遍历,当前元素的索引 = 当前元素值(累计次数) - 当前次数