摘要
不止一次在使用 map 时被卡时限,map 是 c++ 的 STL 中一个常用且方便的容器,其是基于树来实现的,它的插入与查找效率实际上更接近O(log N )(N为插入的元素个数)。当然在 c++ 的 STL 中还有用哈希实现的无序关联容器,这里不做讨论。
在实际应用中,常常会有人把 map 时间复杂度看作O(1),确实在大多数时候 map 表现是令人满意的,但在大量使用的时候,map却不尽人意。
我们将测试如下几种情形下使用 map 容器的效率(时间):
- 仅插入元素(元素类型为int)
- 插入以及查找(元素类型为int)
测试环境准备
为了给定一个对照的标准,先给出如下数据:
- 测试机空循环 1e6 次平均花费 0.0641 s
- 测试机读取 1e6 个int型数据(快读+从文件输入)平均花费 0.2142 s
测试结果
仅插入元素
本机平均花费时间: 1.1015 s
测试代码
const int P = 1e9+7;
map<int,int> mp;
int main(){
int n = 1e6;
long long gap = 1;
for(int i = 1;i <= n;i++){
mp[i*gap%P] = 1; gap += 1;
}
return 0;
}
插入以及查找元素
本机平均花费时间: 1.238 s
测试代码
const int P = 1e9+7;
map<int,int> mp;
int main(){
int n = 1e6;
long long gap = 1;
for(int i = 1;i <= n;i++){
mp[i*gap%P] = 1; gap += 1;
}
for(int i = 1;i <= n;i++)
if(mp.count(i));
return 0;
}
小结
总体上测试结果是符合预期的,虽然 STL 容器已经很优化的,但是毕竟还是用树来实现的,达不到 O(1) 的时间复杂度,所以如果是对时限要求很高的话,最好还是采用手动写哈希表。
上述设计的实验有很多缺陷,如未对 long long转化、取模 以及其它多余的操作进行排除影响,另外本来还测试了char、string、set等类型的元素,但是要设计一个好的测试代码太麻烦了,就删了,总的结论来说就是 int 是所有测试的数据类型中最慢的一种(甚至慢于 set 和 string ,如果只考虑插入和查找)。
最终结论就是如果需要一个 O(1) 时间复杂度的插入和查找(int 类型的元素),那么就用哈希表。