计数排序思路
- 计数排序是一种稳定的时间复杂度算法,其时间复杂度为#card=math&code=O%28n%20%2B%20k%29&id=YfoUg)
- 计数排序本质上是鸽巢原理的应用,是空间换取时间的典型例子。计数排序不是基于比较的排序算法。
- 计数排序引入了一个统计数组,假定其为
rec
,那么rec[i]
表示原始数组中数值等于i
的元素个数。 - 例子:如果有10个人,其中有8个人身高比
Alice
矮,那么,Alice
的身高就是第9矮的。 - 算法流程如下:
- 找出待排序数组中最大和最小的元素。
- 统计数组中每个数值为
i
的元素出现的个数rec[i]
,存入数组的第i - min_value
项。 - 对所有的计数进行累加,得到前缀和数组
summ[i]
(第0
项是0
)。 - 反向填充目标数组,将每个元素
i
放在目标数组target
的第summ[i + 1] - 1
位置,然后执行summ[i + 1] -= 1
。(怎么理解,对于元i
而言,它前面有多少项?就是summ[i + 1] - 1
项,因为summ[i + 1] = rec[0] + rec[1] + rec[2] + ... rec[i - 1] + rec[i]
,长度是i + 1
。所以,对于当前i
而言,summ[i + 1]
意味着的所有元素的个数,那么。前面有summ[i + 1] - 1
个数,其下标自然就是summ[i + 1] - 1
。
- 以
[3, 1, 2, 1, 2, 5, 5, 5]
为例
计数排序代码
```cppinclude
using namespace std;
void print_arr(vector
vector
vector<int> rec(max_num + 5, 0);
vector<int> summ(max_num + 5, 0);
vector<int> ans(n, 0);
for (int i = 0; i < n; i++) {
nums[i] -= min_num;
rec[nums[i]] += 1;
}
for (int i = 1; i <= max_num + 1; i++) {
summ[i] = summ[i - 1] + rec[i - 1];
}
for (int i = 0; i <= max_num; i++) {
for (int j = 0; j < rec[i]; j++) {
ans[summ[i + 1] - 1] = i + min_num;
summ[i + 1] -= 1;
}
}
return ans;
}
int main() { int n = 0; cout << “please input the size of array: “ << endl; cin >> n;
vector<int> nums(n, 0);
cout << "please input the array" << endl;
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
print_arr(nums);
nums = count_sort(nums);
print_arr(nums);
return 0;
} ```
ps : 关于前缀和与数组,几个基本的图需要记住
- fig1: 前缀和
- fig2: 数组
- fig3: 差分