人的知识就好比一个圆圈,圆圈里面是已知的,圆圈外面是未知的。你知道得越多,圆圈也就越大,你不知道的也就越多。

0%

排序--计数排序

概念

计数排序其实是桶排序的一种特殊情况。当要排序的n个数据,所处的范围并不大的时候,比如最大值是k,我们就可以把数据划分成k个桶。每个桶内的数据值都是相同的,省掉了桶内排序的时间。

计数排序只能用在数据范围不大的场景中,如果数据范围k比要排序的数据n大很多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。

时间复杂度

  • 平均:O(n + k)
  • 最好:O(n + k)
  • 最坏:O(n + k)

空间复杂度

O(n + k)

稳定性

稳定

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class CountingSort implements Sort {

@Override
public int[] sort(int[] arr) {
int n = arr.length;

// 查找数组中数据的范围
int max = arr[0];
for (int i = 1; i < n; ++i) {
if (max < arr[i]) {
max = arr[i];
}
}

// 申请一个计数数组 c,下标大小 [0, max]
int[] c = new int[max + 1];
for (int i = 0; i <= max; ++i) {
c[i] = 0;
}

// 计算每个元素的个数,放入 c 中
for (int value : arr) {
c[value]++;
}

// 依次累加
for (int i = 1; i <= max; ++i) {
c[i] = c[i - 1] + c[i];
}

// 临时数组 r,存储排序之后的结果
int[] r = new int[n];
// 计算排序的关键步骤,有点难理解
for (int i = n - 1; i >= 0; --i) {
int index = c[arr[i]] - 1;
r[index] = arr[i];
c[arr[i]]--;
}

// 将结果拷贝给 a 数组
System.arraycopy(r, 0, arr, 0, n);

return arr;
}

}
小礼物走一走,来 Github 关注我