map/set和unordered_map/unordered_set的区别及其适用情况

本专栏内容为:C++学习专栏,分为初阶和进阶两部分。 通过本专栏的深入学习,你可以了解并掌握C++。
💓博主csdn个人主页:小小unicorn

⏩专栏分类:C++

🚚代码仓库:小小unicorn的代码仓库🚚

🌹🌹🌹关注我带你学习编程知识

目录

map/set与unordered_map/unordered_set的区别

xxx容器与unordered_xxx容器对上层所提供函数接口的名字和功能虽然一致,但它们的底层实现却大不相同,xxx容器和unordered_xxx容器的区别如下:

容器 底层数据结构 是否有序 实现版本 增删查改的效率 迭代器类型
unordered_map/unordered_set 哈希表/散列表 遍历无序 C++11 O ( 1 ) 单向迭代器
map/set 红黑树 遍历有序 c++98 O(logN) 双向迭代器

map/set与unordered_map/unordered_set的性能测试

map容器与unordered_map容器的差别和set容器与unordered_set容器的差别类似,下面我们以set容器和unordered_set容器的测试为例。

说到一个容器的性能,我们最关心的实际就是该容器增删查改的效率。我们可以通过下列代码测试set容器和unordered_set容器insert、find以及erase的效率。

cpp 复制代码
#include <iostream>
#include <set>
#include <unordered_set>
#include <time.h>
using namespace std;
int main()
{
	int N = 1000;
	vector<int> v;
	v.reserve(N);
	srand((unsigned int)time(NULL));
	//随机生成N个数字
	for (int i = 0; i < N; i++)
	{
		v.push_back(rand());
	}
	/****************插入效率测试****************/
	//将这N个数插入set容器
	set<int> s;
	clock_t begin1 = clock();
	for (auto e : v)
	{
		s.insert(e);
	}
	clock_t end1 = clock();
	//将这N个数插入unordered_set容器
	unordered_set<int> us;
	clock_t begin2 = clock();
	for (auto e : v)
	{
		us.insert(e);
	}
	clock_t end2 = clock();
	//分别输出插入set容器和unordered_set容器所用的时间
	cout << "set insert: " << end1 - begin1 << endl;
	cout << "unordered_set insert: " << end2 - begin2 << endl;
	/****************查找效率测试****************/
	//在set容器中查找这N个数
	clock_t begin3 = clock();
	for (auto e : v)
	{
		s.find(e);
	}
	clock_t end3 = clock();
	//在unordered_set容器中查找这N个数
	clock_t begin4 = clock();
	for (auto e : v)
	{
		us.find(e);
	}
	clock_t end4 = clock();
	//分别输出在set容器和unordered_set容器中查找这N个数所用的时间
	cout << "set find: " << end3 - begin3 << endl;
	cout << "unordered_set find: " << end4 - begin4 << endl;
	/****************删除效率测试****************/
	//将这N个数从set容器中删除
	clock_t begin5 = clock();
	for (auto e : v)
	{
		s.erase(e);
	}
	clock_t end5 = clock();

	//将这N个数从unordered_set容器中删除
	clock_t begin6 = clock();
	for (auto e : v)
	{
		us.erase(e);
	}
	clock_t end6 = clock();
	//分别输出将这N个数从set容器和unordered_set容器中删除所用的时间
	cout << "set erase: " << end5 - begin5 << endl;
	cout << "unordered_set erase: " << end6 - begin6 << endl;
	return 0;
}

对1000个数做增删查改操作

当N为1000时,set容器和unordered_set容器增删查改的效率差异并不大,在Debug版本下的测试结果如下:

在Release版本下,set容器和unordered_set容器对1000个数做增删查改操作所用的时间更是被优化到了接近0毫秒。

对10000000个数做增删查改操作

而当N为10000000时,set容器和unordered_set容器增删查改的效率的差异就很明显了,在Debug版本下的测试结果如下:

而经过Release版本优化后,unordered_set容器对10000000个数做查找和删除操作所用的时间还是被优化到了接近0毫秒,插入操作所用的时间也仅仅是0.1秒左右。但是set容器对10000000个数做增删查改操作所用的时间还是需要1秒左右,与unordered_set容器相比就占了下风。

注意: 这里给出的N值仅作参考,在不同的测试环境下可能不同。

结论

根据测试结果可以得出以下结论:

  1. 当处理数据量小时,map/set容器与unordered_map/unordered_set容器增删查改的效率差异不大。
  2. 当处理数据量大时,map/set容器与unordered_map/unordered_set容器增删查改的效率相比,unordered系列容器的效率更高。
  3. 因此,当处理数据量较小时,选用xxx容器与unordered_xxx容器的差异不大;当处理数据量较大时,建议选用对应的unordered_xxx容器。

补充一点: 当需要存储的序列为有序时,应该选用map/set容器。

相关推荐
滨HI023 分钟前
C++ opencv简化轮廓
开发语言·c++·opencv
学习路上_write37 分钟前
FREERTOS_互斥量_创建和使用
c语言·开发语言·c++·stm32·单片机·嵌入式硬件
闻缺陷则喜何志丹2 小时前
【SOSDP模板 容斥原理 逆向思考】3757. 有效子序列的数量|分数未知
c++·算法·力扣·容斥原理·sosdp·逆向思考
BestOrNothing_20152 小时前
一篇搞懂 C++ 重载:函数重载 + 运算符重载,从入门到会用(含 ++、<<、== 实战)
c++·函数重载·运算符重载·operator·前置后置++·重载与重写
2501_941144422 小时前
Python + C++ 异构微服务设计与优化
c++·python·微服务
程序猿编码3 小时前
PRINCE算法的密码生成器:原理与设计思路(C/C++代码实现)
c语言·网络·c++·算法·安全·prince
charlie1145141914 小时前
深入理解C/C++的编译链接技术6——A2:动态库设计基础之ABI设计接口
c语言·开发语言·c++·学习·动态库·函数
Cx330❀4 小时前
C++ STL set 完全指南:从基础用法到实战技巧
开发语言·数据结构·c++·算法·leetcode·面试
zmzb01034 小时前
C++课后习题训练记录Day33
开发语言·c++
Want5954 小时前
C/C++贪吃蛇小游戏
c语言·开发语言·c++