Skip to content

Commit 433d20e

Browse files
committed
修复计数排序的异常,让原始序列的最大值+1作为计数容器的大小;解决算法目录与STL算法目录的链接冲突问题
1 parent 056ea33 commit 433d20e

File tree

2 files changed

+46
-36
lines changed

2 files changed

+46
-36
lines changed

Diff for: Algorithm/CountSort.cpp

+42-32
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,61 @@
22
33
计数排序:统计小于等于该元素值的元素的个数i,于是该元素就放在目标数组的索引i位(i≥0)。
44
5-
计数排序基于一个假设,待排序数列的所有数均出现在(0,k)的区间之内,如果k过大则会引起较大的空间复杂度
6-
计数排序并非是一种基于比较的排序方法,它直接统计出键值本应该出现的位置
7-
时间复杂度为O(n),空间复杂度为O(n+k)
5+
计数排序基于一个假设,待排序数列的所有数均为整数,且出现在(0,k)的区间之内。
6+
如果 k(待排数组的最大值) 过大则会引起较大的空间复杂度,一般是用来排序 0 到 100 之间的数字的最好的算法,但是它不适合按字母顺序排序人名。
7+
计数排序不是比较排序,排序的速度快于任何比较排序算法。
8+
时间复杂度为 O(n+k),空间复杂度为 O(n+k)
9+
10+
算法的步骤如下:
11+
12+
1. 找出待排序的数组中最大和最小的元素
13+
2. 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项
14+
3. 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加)
15+
4. 反向填充目标数组:将每个元素 i 放在新数组的第 C[i] 项,每放一个元素就将 C[i] 减去 1
816
917
*****************/
1018

1119

12-
#include<iostream>
13-
#include<vector>
20+
#include <iostream>
21+
#include <vector>
22+
#include <algorithm>
1423

1524
using namespace std;
1625

17-
void countSort(vector<int>& vec,vector<int>& objVec)
26+
// 计数排序
27+
void CountSort(vector<int>& vecRaw, vector<int>& vecObj)
1828
{
19-
vector<int> range(10,0); //range的下标即键值
20-
for(int i=0;i<vec.size();++i)
21-
{//统计每个键值出现的次数
22-
range[vec[i]]++;
23-
}
24-
25-
for(int i=1;i<vec.size();++i)
26-
{//后面的键值出现的位置为前面所有键值出现的次数之和
27-
range[i]+=range[i-1];
28-
}
29-
//至此,range中存放的是相应键值应该出现的位置
30-
int length=vec.size();
31-
for(int i=length-1;i>=0;--i) //注意一个小细节,统计时最正序的,这里是逆序
32-
{//如果存在相同的键值,为了保持稳定性,后出现的应该还是位于后面
33-
//如果正序,则先出现的会放置到后面,因此不再稳定
34-
objVec[range[vec[i]]]=vec[i]; //将键值放到目标位置
35-
range[vec[i]]--;
36-
}
29+
// 确保待排序容器非空
30+
if (vecRaw.size() == 0)
31+
return;
32+
33+
// 使用 vecRaw 的最大值 + 1 作为计数容器 countVec 的大小
34+
int vecCountLength = (*max_element(begin(vecRaw), end(vecRaw))) + 1;
35+
vector<int> countVec(vecCountLength, 0);
36+
37+
// 统计每个键值出现的次数
38+
for (int i = 0; i < vecRaw.size(); i++)
39+
countVec[vecRaw[i]]++;
40+
41+
// 后面的键值出现的位置为前面所有键值出现的次数之和
42+
for (int i = 1; i < vecCountLength; i++)
43+
countVec[i] += countVec[i - 1];
44+
45+
// 将键值放到目标位置
46+
for (int i = vecRaw.size(); i > 0; i--) // 此处逆序是为了保持相同键值的稳定性
47+
vecObj[--countVec[vecRaw[i - 1]]] = vecRaw[i - 1];
3748
}
3849

3950
int main()
4051
{
41-
int a[14]={0,5,7,9,6,3,4,5,2,8,6,9,2,1};
42-
vector<int> vec(a,a+14);
43-
vector<int> objVec(14,0);
44-
45-
countSort(vec,objVec);
52+
vector<int> vecRaw = { 0,5,7,9,6,3,4,5,2,8,6,9,2,1 };
53+
vector<int> vecObj(vecRaw.size(), 0);
4654

47-
for(int i=0;i<objVec.size();++i)
48-
cout<<objVec[i]<<" ";
49-
cout<<endl;
55+
CountSort(vecRaw, vecObj);
5056

57+
for (int i = 0; i < vecObj.size(); ++i)
58+
cout << vecObj[i] << " ";
59+
cout << endl;
60+
5161
return 0;
5262
}

Diff for: README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -1229,11 +1229,11 @@ class doSomething(Flyable *obj) // 做些事情
12291229

12301230
## STL
12311231

1232-
### 索引
1232+
### STL 索引
12331233

1234-
[STL 方法含义](https://github.com/huihut/interview/tree/master/STL)
1234+
[STL 方法含义索引](https://github.com/huihut/interview/tree/master/STL)
12351235

1236-
### 容器
1236+
### STL 容器
12371237

12381238
容器 | 底层数据结构 | 时间复杂度 | 有无序 | 可不可重复 | 其他
12391239
---|---|---|---|---|---
@@ -1253,7 +1253,7 @@ hash_multiset|哈希表|插入、删除、查找 O(1) 最差 O(n)|无序|可重
12531253
hash_map|哈希表|插入、删除、查找 O(1) 最差 O(n)|无序|不可重复|
12541254
hash_multimap|哈希表|插入、删除、查找 O(1) 最差 O(n)|无序|可重复|
12551255

1256-
### 算法
1256+
### STL 算法
12571257

12581258
算法 | 底层算法 | 时间复杂度 | 可不可重复
12591259
---|---|---|---

0 commit comments

Comments
 (0)