c++ std中set与unordered_set区别和map与unordered_map区别类似,其底层的数据结构说明如下:

  1、set基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的。

  2、unordered_set基于哈希表,数据插入和查找的时间复杂度很低,几乎是常数时间,而代价是消耗比较多的内存,无自动排序功能。底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash函数对key进行映射到不同区域进行保存。

更详细的区别,如下图:

 set与unordered相比:

  1、set比unordered_set使用更少的内存来存储相同数量的元素。

  2、对于少量的元素,在set中查找可能比在unordered_set中查找更快。

  3、尽管许多操作在unordered_set的平均情况下更快,但通常需要保证set在最坏情况下有更好的复杂度(例如insert)。

  4、如果您想按顺序访问元素,那么set对元素进行排序的功能是很有用的。

  5、您可以用<、<=、>和>=从字典顺序上比较不同的set集。unordered_set集则不支持这些操作。

一般来说,在如下情况,适合使用set:

  1、我们需要有序的数据(不同元素)。

  2、我们必须打印/访问数据(按排序顺序)。

  3、我们需要知道元素的前任/继承者。

一般来说,在如下情况,适合使用unordered_set:

  1、我们需要保留一组元素,不需要排序。

  2、我们需要单元素访问,即不需要遍历。

  3、仅仅只是插入、删除、查找的话。

示例:

set:

Input : 1, 8, 2, 5, 3, 9
Output : 1, 2, 3, 5, 8, 9

unordered_set:

Input : 1, 8, 2, 5, 3, 9
Output : 9 3 1 8 2 5 (顺序依赖于 hash function)

下面再给出一个以vector<int>为key的示例,对比下set与unordered_set:

1 set<vector<int>> s;
2 s.insert({1, 2});
3 s.insert({1, 3});
4 s.insert({1, 2});
5
6 for(const auto& vec:s)
7 cout<<vec<<endl;
8 // 1 2
9 // 1 3

因为vector重载了operator<,因此可以作为set的key。

但是如果直接使用unordered_set<vector<int>> s;则报错,因为vector没有hash函数,需要自己定义一个,可以定义一个类似下面这样的hash函数:

 1 struct VectorHash {
2 size_t operator()(const std::vector<int>& v) const {
3 std::hash<int> hasher;
4 size_t seed = 0;
5 for (int i : v) {
6 seed ^= hasher(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
7 }
8 return seed;
9 }
10 };

接下来这样使用:

1 unordered_set<vector<int>, VectorHash> s;
2 s.insert({1, 2});
3 s.insert({1, 3});
4 s.insert({1, 2});
5
6 for(const auto& vec:s)
7 cout<<vec<<endl;
8 // 1 2
9 // 1 3

或者模板特化struct hash<std::vector<int>>

 1 namespace std {
2 template<>
3 struct hash<std::vector<int>> {
4 size_t operator()(const vector<int> &v) const {
5 std::hash<int> hasher;
6 size_t seed = 0;
7 for (int i : v) {
8 seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
9 }
10 return seed;
11 }
12 };
13 }
14
15 // usage example
16 void test_unordered_set(){
17 unordered_set<std::vector<int>> s;
18 s.insert({1, 2});
19 s.insert({1, 3});
20 s.insert({1, 2});
21 for(const auto& vec:s)
22 cout<<vec<<endl;
23 // 1 3
24 // 1 2
25
26 std::hash<int> hasher;
27 cout<<"hasher(99): "<<hasher(99)<<" ,hasher(77): "<<hasher(77)<<endl;
28 // hasher(99): 99 ,hasher(77): 77
29 }

可以看到,在某些情况下,unordered_set的使用门槛还是挺高的。

Input : 1, 8, 2, 5, 3, 9
Output : 1, 2, 3, 5, 8, 9

c++ set与unordered set的区别的更多相关文章

  1. 2.8 C++STL set/multiset容器详解

    文章目录 2.8.1 引入 2.8.2 代码示例 2.8.3 代码运行结果 2.8.4 对组pair的补充 代码实例 运行结果 总结 2.8.1 引入 set/multiset容器概念 set和mul ...

  2. mootools里选择器$,$$,$E,$ES等的区别

    区别就是 $和$$都是1个参数, $适用于ID,或者ID代表的对象 $$适用于CSS选择器 $E和$ES,有2个参数,第二个参数是可选参数代表(filter,即某个ID范围里的元素) $E('inpu ...

  3. html中ul,ol和li的区别

    ul是无序列表,全称是unordered list,先来个例子:    ●张三    ●李四    ●王二    ●刘五   ol是有序列表 ,全称是ordered list,同样举个例子:  1.张 ...

  4. c#与java的区别

    经常有人问这种问题,用了些时间java之后,发现这俩玩意除了一小部分壳子长的还有能稍微凑合上,基本上没什么相似之处,可以说也就是马甲层面上的相似吧,还是比较短的马甲... 一般C#多用于业务系统的开发 ...

  5. jquery和Js的区别和基础操作

    jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...

  6. 【原】nodejs全局安装和本地安装的区别

    来微信支付有2年多了,从2年前的互联网模式转变为O2O模式,主要的场景是跟线下的商户去打交道,不像以往的互联网模式,有产品经理提需求,我们帮忙去解决问题. 转型后是这样的,团队成员更多需要去寻找业务的 ...

  7. 探究@property申明对象属性时copy与strong的区别

    一.问题来源 一直没有搞清楚NSString.NSArray.NSDictionary--属性描述关键字copy和strong的区别,看别人的项目中属性定义有的用copy,有的用strong.自己在开 ...

  8. X86和X86_64和X64有什么区别?

    x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...

  9. Java中Comparable与Comparator的区别

    相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...

随机推荐

  1. Nginx网站服务 配置

    Nginx网站服务 配置 1.编译安装Nginx服务 2.认识Nginx服务的主配置文件nginx.conf 3.访问状态统计配置 4.基于授权的访问控制 5.基于客户端的访问控制 6.基于域名的Ng ...

  2. SpringMVC探秘-请求之路

    SpringMVC探秘-请求之路 开始 今天来分析一下SpringMVC的原理,探究SpringMVC如何把请求传递到每个Controller的方法上,从Servlet到Controller,一个请求 ...

  3. 基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版

    对于做海洋数据处理的同学,会经常遇到nc格式的文件,nc文件的格式全称是NetCDF,具体的详细解释请查询官网[https://www.unidata.ucar.edu/software/netcdf ...

  4. 4、Linux基础--系统目录

    笔记 1.晨考 1.移动文件的命令 mv 2.删除文件的命令及其参数 rm 参数: -r : 递归删除 -f : 不提示删除 -i : 提示删除 3.复制文件的命令及其参数 cp 参数: -r : 递 ...

  5. Solution -「ARC 063D」「AT 2149」Snuke's Coloring 2

    \(\mathcal{Decription}\)   Link.   平面上有一个左下角坐标 \((0,0)\) 右上角坐标 \((W,H)\) 的矩形,起初长方形内部被涂白. 现在给定 \(n\) ...

  6. C1 能力认证——Web进阶

    C1 能力认证--Web进阶 DOM节点操作-上 名称 描述 getElementById() 获取带有指定id的节点 getElementsByTagName() 获取带有指定标签名的节点集合 qu ...

  7. suse 12 sp3 利用shell脚本离线编译安装ansible

    # 测试环境是suse 12 sp3的系统,机器都是内网使用的,安装ansible真的很难顶 # 测试环境使用的python版本:2.7.13-27 # 此脚本只在本人测试环境成功,其他环境,需要选择 ...

  8. 【曹工杂谈】Mysql-Connector-Java时区问题的一点理解--写入数据库的时间总是晚13小时问题

    背景 去年写了一篇"[曹工杂谈]Mysql客户端上,时间为啥和本地差了整整13个小时,就离谱",结果最近还真就用上了. 不是我用上,是组内一位同事,他也是这样:有个服务往数据库in ...

  9. spring中容器和对象的创建流程

    容器和对象的创建流程 1.先创建容器 2.加载配置文件,封装成BeanDefinition 3.调用执行BeanFactoryPostProcessor 准备工作: 准备BeanPostProcess ...

  10. centos7对外开放端口号

    前提:防火墙处于打开状态 1:查看防护墙启动状态:systemctl  status firewalld 2:开启:systemctl start firewalld 3:关闭:systemctl s ...