当前位置: 首页 > news >正文

【STL库】unordered_map/unordered_set 类学习

在这里插入图片描述

🫧 励志不掉头发的内向程序员:个人主页

 ✨️ 个人专栏: 《C++语言》《Linux学习》

🌅偶尔悲伤,偶尔被幸福所完善


👓️博主简介:

在这里插入图片描述

文章目录

  • 前言
  • 一、unordered_set 系列的使用
    • 1.1、unordered_set 和 unordered_multiset 参考文档
    • 1.3、类函数学习
  • 二、unordered_set 和 set 的使用差异
  • 三、unordered_map 系列的使用
    • 3.1、unordered_map 和 unordered_multimap 参考文档
    • 3.2、unordered_map 类的介绍
    • 3.3、类函数学习
  • 四、unordered_map 和 map 的使用差异
  • 五、unordered_multimap/unordered_multiset
  • 总结


前言

我们在学习完 map/set 的底层原理和实现时,大家会不会有一种疑惑,map/set 的底层红黑树已经这么麻烦了,查找效率也只能达到 O(logN),那有没有查找效率是 O(1) 的容器呢,查找效率是 O(1) 的容器它的结构会不会比红黑树还要复杂的多呢?当然是有的,这就是我们的哈希表,也就是我们 unordered_map/unordered_set 容器。它的实现不会有大家想象的那么复杂,所以大家放心。当然,按流程来说我们先来了解了解它的接口吧。

在这里插入图片描述


一、unordered_set 系列的使用

1.1、unordered_set 和 unordered_multiset 参考文档

我们大家可以打开参考文档自行查看:<unordered_set> - C++ Reference


## 1.2、unordered_set 类的介绍 >我们来看看 unordered_set 类的声明,来分辨分辨它和 set 有什么区别。

在这里插入图片描述

  • Key 就是 unordered_set 底层关键字的类型
  • unordered_set 默认要求 Key 支持转换为整形,如果不支持或者想按自己的需求走可以自行实现支持将 Key 转成整形的仿函数传给第二个模板参数
  • unordered_set 默认要求 Key 支持比较相等,如果不支持或者想按自己的需求走可以自行实现支持将 Key 比较相等的仿函数传给第三个模板参数
  • unordered_set 底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第四个参数
  • ⼀般情况下,我们都不需要传后三个模板参数
  • unordered_set 底层是用哈希桶实现,增删查平均效率是 O(1),迭代器遍历不再有序,为了跟 set 区分,所以取名unordered_set
  • 前面部分我们已经学习了 set 容器的使用,set 和 unordered_set 的功能高度相似,只是底层结构不同,有⼀些性能和使用的差异,这⾥我们只讲他们的差异部分。

1.3、类函数学习

我们 unordered_set 和 set 基本上是一样的,所以我们主要就只讲讲不同的地方,其他的就一笔带过了

(1)构造函数
默认构造:
在这里插入图片描述

unordered_set<int> us1;

迭代器区间构造:
在这里插入图片描述

vector<int> v({ 1, 2, 3, 4, 5, 6 });
unordered_set<int> us2(v.begin(), v.end());

拷贝构造: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/3d9586cec76f4881af96ba932d9106d5.png#pic_center =700x)
unordered_set<int> us3(us2);

列表构造: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b271a9a192db40b8948fad52c5c38820.png#pic_center =700x)
unordered_set<int> us4({ 1, 2, 3, 4, 5 , 6, 7, 8 });

(2)迭代器
在这里插入图片描述
unordered_set 迭代器不支持反向遍历,只能正向遍历。

unordered_set<int> us1({ 1, 2, 3, 4, 5 , 6, 7, 8 });unordered_set<int>::iterator it = us1.begin();
while (it != us1.end())
{cout << *it << " ";++it;
}
cout << endl;

在这里插入图片描述
当然,它的输出是随机输出的,而非按顺序输出。

unordered_set<int> us1({ 3, 4, 1, 0, 9, 2, 5, 6 });

在这里插入图片描述
它也具有去重的功能。

unordered_set<int> us1({ 3, 4, 1, 0, 9, 2, 5, 6, 1, 5, 3, 1 ,5 });

在这里插入图片描述


(3)增删查
增:
直接插入数值
在这里插入图片描述

unordered_set<int> us1;
us1.insert(1);
us1.insert(2);
us1.insert(3);
us1.insert(4);

在这里插入图片描述

插入一个迭代器区间
在这里插入图片描述

unordered_set<int> us1;
vector<int> v({ 2, 3, 6, 1, 8, 7 });
us1.insert(v.begin(), v.end());

在这里插入图片描述

插入一个列表
在这里插入图片描述

unordered_set<int> us1;
us1.insert({ 1, 4, 2, 8, 5 });

在这里插入图片描述


删:
和 set 完全一样,都是删除一个迭代器位置、删除一个值和删除一个迭代器区间,这里就不过多赘述。
在这里插入图片描述


查:
在这里插入图片描述
和 set 相同,找到了就返回那个位置的迭代器,否则就返回 end()。

unordered_set<int> us1({ 3, 4, 1, 0, 9, 2, 5, 6 });auto u1 = us1.find(5);
cout << *u1 << endl;auto u2 = us1.find(100);
cout << *(--u2) << endl;

在这里插入图片描述


二、unordered_set 和 set 的使用差异

查看文档我们会发现 unordered_set 的支持增删查和 set 的使用一模一样,关于使用我们这里就不再继续赘述和演示了。

  • unordered_set 和 set 的第一个差异是对 key 的要求不同,set 要求 Key 支持小于比较,而 unordered_set 要求 Key 支持转成整形且支持等于比较,要理解 unordered_set 的这个两点要求得后续我们结合哈希表底层实现才能真正理解,也就是说这本质是哈希表的要求。
  • unordered_set 和 set 的第二个差异是迭代器的差异,set 的 iterator 是双向迭代器,unordered_set 是单向迭代器,其次 set 底层是红黑树,红黑树是⼆叉搜索树,⾛中序遍历是有序的,所以 set 迭代器遍历是有序 + 去重。而 unordered_set 底层是哈希表,迭代器遍历是无序 + 去重。
  • unordered_set 和 set 的第三个差异是性能的差异,整体而言大多数场景下,unordered_set 的增删查改更快一些,因为红黑树增删查改效率是 O(logN),而哈希表增删查平均效率是 O(1) 。

三、unordered_map 系列的使用

3.1、unordered_map 和 unordered_multimap 参考文档

我们大家可以打开参考文档自行查看:<unordered_map> - C++ Reference


3.2、unordered_map 类的介绍

在这里插入图片描述

  • Key 就是 unordered_map 底层关键字的类型
  • T 就是 unordered_map 与 Key 所对应的值的类型
  • unordered_map 默认要求 Key 支持转换为整形,如果不支持或者想按自己的需求走可以自行实现支持将 Key 转成整形的仿函数传给第二个模板参数
  • unordered_map 默认要求 Key 支持比较相等,如果不支持或者想按自己的需求走可以自行实现支持将 Key 比较相等的仿函数传给第三个模板参数
  • unordered_map 底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第四个参数
  • ⼀般情况下,我们都不需要传后三个模板参数
  • unordered_map 底层是用哈希桶实现,增删查平均效率是 O(1),迭代器遍历不再有序,为了跟 map 区分,所以取名unordered_map
  • 前面部分我们已经学习了 map 容器的使用,map 和 unordered_map 的功能高度相似,只是底层结构不同,有⼀些性能和使用的差异,这⾥我们只讲他们的差异部分。

3.3、类函数学习

我们 unordered_map 和 map 基本上是一样的,所以我们主要就只讲讲不同的地方,其他的就一笔带过了

(1)构造函数
默认构造:
在这里插入图片描述

unordered_map<int, int> um1;

迭代器区间构造:
在这里插入图片描述

vector<pair<int, int>> v({ {1, 2}, {2, 2}, {3, 2}, {4, 2} });
unordered_map<int, int> um2(v.begin(), v.end());

拷贝构造:

在这里插入图片描述

unordered_map<int, int> um3(um2);

列表构造: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4d2d325e4beb4825aeba9d2d5195c635.png#pic_center =600x)
unordered_map<int, int> um4({ {1, 2}, {2, 2}, {3, 2}, {4, 2} });

(2)迭代器

unordered_map 迭代器不支持反向遍历,只能正向遍历。
在这里插入图片描述

unordered_map<int, int> um1({ {3, 2}, {4, 2}, {1, 2}, {9, 2}, {5, 2} });
unordered_map<int, int>::iterator it = um1.begin();
while (it != um1.end())
{cout << it->first << " " << it->second << endl;it++;
}
cout << endl;

在这里插入图片描述
他的内容也是随机输出的,而非按顺序输出。unordered_map 具有去重的功能。

unordered_map<int, int> um1({ {3, 2}, {4, 2}, {1, 2}, {9, 2}, {5, 2}, {3, 7}, {1, 4} });

和 map 是一样的。
在这里插入图片描述


(3)增删查
和 map 是一样的,这里也就不多说了,大家可以自己去看看参考文档。

四、unordered_map 和 map 的使用差异

查看文档我们会发现 unordered_map 的支持增删查改和 map 的使用一模一样,关于使用我们这里也就不再继续赘述和演示了。

  • unordered_map 和 map 的第一个差异是对 key 的要求不同,map 要求 Key 支持小于比较,而 unordered_map 要求 Key 支持转成整形且支持等于比较,要理解 unordered_map 的这个两点要求得后续我们结合哈希表底层实现才能真正理解,也就是说这本质是哈希表的要求。
  • unordered_map 和 map 的第二个差异是迭代器的差异,map 的 iterator 是双向迭代器,unordered_map 是单向迭代器,其次map 底层是红黑树,红黑树是二叉搜索树,⾛中序遍历是有序的,所以 map 迭代器遍历是 Key 有序 + 去重。而 unordered_map 底层是哈希表,迭代器遍历是 Key 无序 + 去重。
  • unordered_map 和 map 的第三个差异是性能的差异,整体而言大多数场景下,unordered_map 的增删查改更快⼀些,因为红黑树增删查改效率是 O(logN),而哈希表增删查平均效率是 O(1)。

五、unordered_multimap/unordered_multiset

  • unordered_multimap/unordered_multiset 跟 multimap/multiset 功能完全类似,支持 Key 冗余。
  • unordered_multimap/unordered_multiset 跟 multimap/multiset 的差异也是三个方面的差异,key 的要求的差异,iterator 及遍历顺序的差异,性能的差异。


总结

以上便是我们 unordered_map/unordered_set 类函数的全部学习内容,因为我们前面已经学习过非常多的容器了,而且这里也和我们前面 map/set 上层几乎是一样的,只是效率的区别,所以我们赶快讲完它类函数的使用,去看看它是怎么实现我们 O(1) 效率的查找的吧,我们下一章再见。

在这里插入图片描述

🎇坚持到这里已经很厉害啦,辛苦啦🎇
ʕ • ᴥ • ʔ
づ♡ど

文章转载自:

http://5oWlYjmE.bhkLt.cn
http://dHoxbs6G.bhkLt.cn
http://uExAOWAq.bhkLt.cn
http://PoMHrgxN.bhkLt.cn
http://fDKLGiiG.bhkLt.cn
http://NUFiqz8N.bhkLt.cn
http://TVDErRWr.bhkLt.cn
http://SzebLUvp.bhkLt.cn
http://DB6iU3v6.bhkLt.cn
http://R8oOxcj9.bhkLt.cn
http://CMqult9Z.bhkLt.cn
http://dKOQ6xBk.bhkLt.cn
http://57hlisIh.bhkLt.cn
http://hIQNlLiP.bhkLt.cn
http://9V13nOSv.bhkLt.cn
http://zjZvuWgu.bhkLt.cn
http://tHOn4NwS.bhkLt.cn
http://elyLmtTn.bhkLt.cn
http://4U8fi7vm.bhkLt.cn
http://qB8yqkU9.bhkLt.cn
http://KoAj2G0h.bhkLt.cn
http://P5ow1f0T.bhkLt.cn
http://m7FgkRqj.bhkLt.cn
http://IlixxrHo.bhkLt.cn
http://SC3z86m8.bhkLt.cn
http://w6ygaGi4.bhkLt.cn
http://CHMJ4WvL.bhkLt.cn
http://kYGcF1bL.bhkLt.cn
http://3UYZJ8Ra.bhkLt.cn
http://TRTTpsMK.bhkLt.cn
http://www.dtcms.com/a/384523.html

相关文章:

  • 学习threejs,使用自定义GLSL 着色器,实现水面、粒子特效
  • 机器学习-第二章
  • 贪心算法在SDN流表优化中的应用
  • 植物1区TOP——GWAS eQTL如何精准定位调控棉花衣分的候选基因
  • iOS 灵动岛 ActivityKit 开发实践
  • JVM 垃圾收集器
  • 学习日记-XML-day55-9.14
  • SenseVoice + WebRTC:打造行业级实时语音识别系统的底层原理与架构设计
  • C++ 异常机制深度解析:从原理到实战的完整指南
  • 在 Qoder 等 AI 二创 IDE 里用 VS Code Remote-SSH 的“曲线连接”实战
  • 云计算与大数据技术深入解析
  • 如何用Verdi APP抽出某个指定module的interface hierarchy
  • MySQL 锁机制详解+示例
  • 消息队列的“翻车“现场:当Kafka和RocketMQ遇到异常时会发生什么?
  • 在Cursor上安装检索不到的扩展库cline的方式方法
  • 第二十一章 ESP32S3 IIC_OLED 实验
  • 能取代 transform 的架构目前看来 有哪些
  • 为什么基频是信号速率的1/2?
  • Unity UI坐标说明
  • 微美全息(NASDAQ:WIMI)以声誉混合多层共识,开启区块链共识算法创新篇章
  • LAN9253通过CHIP_MODE改变链路顺序
  • 矩阵运算_矩阵A和向量a的转置T相关
  • C++异步任务处理与消息可靠性保障指南:从基础到实战
  • 总结-十大管理输入输出
  • 【Vue3】09-编写vue时,reactive的使用
  • Transformer原理学习(2)位置编码
  • C++编程语言:标准库:第38章——输入输出流(Bjarne Stroustrup)
  • 北理工提出仅依赖机载传感器针对IAP的控制与状态估计框架
  • JVM 垃圾收集算法详解!
  • pycharm选择conda的interpreter