计数排序 (Counting Sort) 是一种非常高效的排序算法,特别适用于处理范围较小的整数数据。它是通过统计每个元素出现的次数,并根据这些统计信息来进行排序,而不是像传统的比较排序算法那样进行元素之间的比较。
1. 计数排序的基本思路
1.1 找出输入数据的范围:找出输入数据中的最大值和最小值。
2.2 建立计数数组:根据数据范围建立一个计数数组,记录每个元素出现的次数。
3.3 累加计数数组:将计数数组中的值累加,这样每个元素就能知道它的正确位置。
4.4 输出排序结果:根据累加后的计数数组将数据重新放回到原数组或新数组中。
2. 计数排序的时间复杂度
- 时间复杂度:O(n + k),其中 n 是输入数组的大小,k 是数据的范围(即最大值和最小值之间的差值)。
- 空间复杂度:O(k),需要额外的空间来存储计数数组。
3. 计数排序的优缺点
3.1 优点
- 时间复杂度较低,特别适合范围较小的整数排序。
- 对于元素个数很大,但数据范围有限的情况,效率特别高。
3.2 缺点
- 不适用于数据范围过大或者有浮动的小数。
- 空间复杂度较高,尤其是在数据范围 k 非常大时。
4 计数排序的实现
#include <iostream>
#include <vector>
#include <algorithm>
void countingSort(std::vector<int>& arr) {
if (arr.empty()) return;
// 找到最大值和最小值
int max_val = *std::max_element(arr.begin(), arr.end());
int min_val = *std::min_element(arr.begin(), arr.end());
// 创建计数数组,大小为数据范围的大小
std::vector<int> count(max_val - min_val + 1, 0);
// 统计每个元素出现的次数
for (int num : arr) {
count[num - min_val]++;
}
// 通过计数数组将原数组按顺序重新排列
int index = 0;
for (int i = 0; i < count.size(); i++) {
while (count[i] > 0) {
arr[index++] = i + min_val;
count[i]--;
}
}
}
int main() {
std::vector<int> arr = {4, 2, 2, 8, 3, 3, 1};
countingSort(arr);
// 输出排序后的数组
for (int num : arr) {
std::cout << num << " ";
}
return 0;
}
代码解析
- 找最大最小值:首先,程序找出输入数组中的最大值和最小值,用来计算计数数组的范围。
- 创建计数数组:然后,程序创建一个大小为 max_val - min_val + 1 的计数数组,用于记录每个元素出现的次数。
- 统计次数:遍历输入数组,更新计数数组。每次遇到一个元素,就增加它在计数数组中的计数。
- 生成排序结果:根据计数数组的值,按照每个元素的出现次数填充回原数组。
5. 总结
计数排序是一个适用于范围小且整数数据的排序算法。通过统计每个元素的出现次数并根据这些统计信息将数组排序,可以达到非常高的排序效率。
它的时间复杂度为 O(n + k),其中 n 是数组大小,k 是数据范围,适用于数据范围较小的情况。