C++第三十九弹---C++ STL中的无序容器:unordered_set与unordered_map使用详解
✨个人主页: 熬夜学编程的小林
💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】
目录
1 unordered_set
1.1 unordered_set的接口说明
1.1.1 unordered_set的构造
1.1.2. unordered_set的容量
1.1.3. unordered_set的迭代器
1.1.4. unordered_set的查询
1.1.5. unordered_set的修改操作
1.1.6. unordered_set的桶操作
2 unordered_map
1.2 unordered_map的接口说明
1.2.1. unordered_map的构造
1.2.2. unordered_map的容量
1.2.3. unordered_map的迭代器
1.2.4. unordered_map的元素访问
6. unordered_map的修改操作
7. unordered_map的桶操作
在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log2 N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同,本文中只对unordered_map和unordered_set进行介绍。
1 unordered_set
- 1. unordered_set 是以不特定顺序存储唯一元素的容器,并允许根据其值快速检索单个元素。
- 2. 在unordered_set中,元素的值同时是其键,它唯一地标识它。键是不可变的,因此,unordered_set中的元素不能在容器中修改一次,但是,它们可以插入和删除。
- 3. 在内部,unordered_set中的元素不按任何特定顺序排序,而是根据其哈希值组织到桶中,以便直接通过其值快速访问各个元素(平均平均时间复杂度恒定)。
- 4. unordered_set容器通过其键访问单个元素的速度比设置的容器更快,尽管它们在通过其元素子集进行范围迭代时通常效率较低。
- 5. 容器中的迭代器至少是正向迭代器。
1.1 unordered_set的接口说明
1.1.1 unordered_set的构造
代码演示
#include<unordered_set>
int main()
{// 构造空对象unordered_set<int> s1;// 列表构造对象unordered_set<int> s2 = { 1,3,4,9,2,7 };return 0;
}
测试结果

1.1.2. unordered_set的容量
| 函数声明 | 功能介绍 |
|---|---|
| bool empty() const | 检测unordered_set是否为空 |
| size_t size() const | 获取unordered_set的有效元素个数 |
代码演示
#include<unordered_set>
int main()
{unordered_set<int> s1 = { 1,3,4,9,2,7 };cout << "empty() = " << s1.empty() << endl;cout << "size() = " << s1.size() << endl;return 0;
}
测试结果

1.1.3. unordered_set的迭代器
| 函数声明 | 功能介绍 |
|---|---|
| begin | 返回unordered_set第一个元素的迭代器 |
| end | 返回unordered_set最后一个元素下一个位置的迭代器 |
代码演示
#include<unordered_set>
int main()
{unordered_set<int> s1 = { 1,3,4,9,2,7 };// 获取unordered_set第一个元素的迭代器unordered_set<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;return 0;
}
测试结果

1.1.4. unordered_set的查询
| 函数声明 | 功能介绍 |
|---|---|
| iterator find(const K& key) | 返回key在哈希桶中的位置 |
| size_t count(const K& key) | 返回哈希桶中key的个数 |
代码演示
#include<unordered_set>
int main()
{unordered_set<int> s1 = { 1,3,4,9,2,7,4 };// 查找数值3的位置,并打印该位置的值auto pos = s1.find(3);cout << *pos << endl;// 计算数值4的个数size_t countFour = s1.count(4);cout << "countFour = " << countFour << endl;return 0;
}
测试结果

注意:unordered_set中key是不能重复的,因此count函数的返回值最大为1。
1.1.5. unordered_set的修改操作
| 函数声明 | 功能介绍 |
|---|---|
| insert | 向容器中插入key值 |
| erase | 删除容器中的key值 |
| void clear() | 清空容器中有效元素个数 |
| void swap(unordered_set&) | 交换两个容器中的元素 |
代码演示
#include<unordered_set>
int main()
{unordered_set<int> s1;// 插入值s1.insert(1);s1.insert(4);s1.insert(5);// 支持迭代器,因此也支持范围forfor (auto e : s1){cout << e << " ";}cout << endl;// 删除6,没有该值则不删除s1.erase(6);// 删除4,有该值则删除该值s1.erase(4);for (auto e : s1){cout << e << " ";}cout << endl;return 0;
}
测试结果

1.1.6. unordered_set的桶操作
| 函数声明 | 功能介绍 |
|---|---|
| size_t bucket_count()const | 返回哈希桶中桶的总个数 |
| size_t bucket_size(size_t n)const | 返回n号桶中有效元素的总个数 |
| size_t bucket(const K& key) | 返回元素key所在的桶号 |
代码演示
#include<unordered_set>
int main()
{unordered_set<int> s1 = { 1,4,6,9,3,7,5 };// 获取桶的总个数cout << "bucket_count() = " << s1.bucket_count() << endl;// 获取2号桶有效元素个数cout << "bucket_size(2) = " << s1.bucket_size(2) << endl;// 数值6所在的桶号cout << "bucket(6) = " << s1.bucket(6) << endl;return 0;
}
测试结果

2 unordered_map
- 1. unordered_map是存储<key, value>键值对的关联式容器,其允许通过key快速的索引到与其对应的value。
- 2. 在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。
- 3. 在内部,unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。
- 4. unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。
- 5. unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。
- 6. 它的迭代器至少是前向迭代器。
1.2 unordered_map的接口说明
1.2.1. unordered_map的构造
| 函数声明 | 功能介绍 |
|---|---|
| unordered_map | 构造一个空的 unordered_map 对象 |
| unordered_map(initializer_list<T> il) | 使用列表的内容初始化容器。 |
代码演示
#include<unordered_map>
int main()
{// 构造空对象unordered_map<string,int> m1;// 列表构造对象unordered_map<string, string> m2 = {{"insert","插入"},{"erase","删除"},{"string","字符串"} };return 0;
}
测试结果

1.2.2. unordered_map的容量
| 函数声明 | 功能介绍 |
|---|---|
| bool empty() const | 检测unordered_map是否为空 |
| size_t size() const | 获取unordered_map的有效元素个数 |
代码演示
#include<unordered_map>
int main()
{unordered_map<string, string> m1 = {{"insert","插入"},{"erase","删除"},{"string","字符串"} };cout << "empty() = " << m1.empty() << endl;cout << "size() = " << m1.size() << endl;return 0;
}
测试结果

1.2.3. unordered_map的迭代器
| 函数声明 | 功能介绍 |
|---|---|
| begin | 返回unordered_map第一个元素的迭代器 |
| end | 返回unordered_map最后一个元素下一个位置的迭代器 |
代码演示
#include<unordered_map>
int main()
{unordered_map<string, string> m1 = {{"insert","插入"},{"erase","删除"},{"string","字符串"} };// 获取第一个元素的迭代器,使用auto更简便//unordered_map<string, string>::iterator it = m1.begin();auto it = m1.begin();while (it != m1.end()){cout << it->first << ":" << it->second << endl;++it;}cout << endl;return 0;
}
测试结果

1.2.4. unordered_map的元素访问
| 函数声明 | 功能介绍 |
|---|---|
| operator[] | 返回与key对应的value,没有一个默认值 |
代码演示
#include<unordered_map>
int main()
{// 统计各自水果的个数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };unordered_map<string, int> countMap;for (auto& e : arr){// 水果没有出现则插入该水果,出现则将个数++countMap[e]++;}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}cout << endl;return 0;
}
测试结果

注意:该函数中实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,将key对应的value返回。此处与map中的operator[]原理类似。
1.2.5. unordered_map的查询
| 函数声明 | 功能介绍 |
|---|---|
| iterator find(const K& key) | 返回key在哈希桶中的位置 |
| size_t count(const K& key) | 返回哈希桶中关键码为key的键值对的个数 |
代码演示
#include<unordered_map>
int main()
{unordered_map<string, int> m1 = {{"string",1 }, { "insert",2 }, { "left",3 } };// 查找left的位置,打印该位置键值对的值auto pos = m1.find("left");cout << pos->first << ":" << pos->second << endl;// 计算key为string的键值对个数size_t count = m1.count("string");cout << "count = " << count << endl;return 0;
}
测试结果

注意:unordered_map中key是不能重复的,因此count函数的返回值最大为1。
6. unordered_map的修改操作
| 函数声明 | 功能介绍 |
|---|---|
| insert | 向容器中插入键值对 |
| erase | 删除容器中的键值对 |
| void clear() | 清空容器中有效元素个数 |
| void swap(unordered_map&) | 交换两个容器中的元素 |
代码演示
#include<unordered_map>
int main()
{unordered_map<string, int> m1;pair<string, int> kv1("string", 1);// 插入值m1.insert(kv1);// 有名对象m1.insert({ "left",2 });m1.insert(make_pair("right", 3));for (auto e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;// 删除key为string的键值对m1.erase("string");for (auto e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}
测试结果

7. unordered_map的桶操作
| 函数声明 | 功能介绍 |
|---|---|
| size_t bucket_count()const | 返回哈希桶中桶的总个数 |
| size_t bucket_size(size_t n)const | 返回n号桶中有效元素的总个数 |
| size_t bucket(const K& key) | 返回元素key所在的桶号 |
代码演示
#include<unordered_map>
int main()
{unordered_map<string, int> m1 = {{"string",1},{"right",2},{"insert",3}};// 获取桶的总个数cout << "bucket_count() = " << m1.bucket_count() << endl;// 获取3号桶有效元素个数cout << "bucket_size(2) = " << m1.bucket_size(3) << endl;// key为right所在的桶号cout << "bucket(right) = " << m1.bucket("right") << endl;return 0;
}
测试结果

相关文章:
C++第三十九弹---C++ STL中的无序容器:unordered_set与unordered_map使用详解
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1 unordered_set 1.1 unordered_set的接口说明 1.1.1 unordered_set的构造 1.1.2. unordered_set的容量 1.1.3. unordered_set的迭代器 1.1…...
数学建模起步感受(赛前15天)
0基础直接上手数模,因为大一!年轻就是无所畏惧!开个玩笑,因为数模比赛比一年少一年… 抱着不打也是浪费的态度,我开始着手准备 首先python啥也不会,知道有元组这玩意… 仅仅在刷软考题的时候遇到python选择…...
【YOLO5 项目实战】(4)红外目标检测
欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【YOLO5 项目实战】(1)YOLO5 环境配置与测试 【YOLO5 项目实战】(2)使用自己的数据集训练目标检测模型 【YOLO5 项目实战】(3)P…...
游泳耳机哪个牌子好?角逐必选榜的4大王者游泳耳机测评解析!
在选择游泳耳机时,许多消费者往往会被市场上五花八门的产品所困扰。特别是那些标榜能够防水防潮的产品,但实际上它们往往缺乏核心技术支持,存在很高的损伤风险。据调查,超过90%的用户反映,市面上的游泳耳机常常无法达到…...
鹤岗房全国蔓延,现在要不要买房?
文|琥珀食酒社 作者 | 积溪 房子卖白菜价、人人都能买得起的时代 真的要来了 以前啊你花2万块钱 在大城市买不到一个厕所 可现在只要几万块你就能买一整套房 还带装修和家电 而且这样的房子还很多 “鹤岗”房已经在全国快速蔓延 那对咱普通人来说到底是好…...
Flink程序部署与提交
前言 我们看门见山,生产环境一般用的是在YARN上面采用应用模式进行部署flink程序。实际生产中一般需要和资源管理平台(如YARN)结合起来,选择特定的模式来分配资源、部署应用。 部署模式 在一些应用场景中,对于集群资源分配和占用的方式,可能会有特定的需求。Flink 为各…...
了解Android
Android 系统架构 从图中可以看出,整个Android操作系统分为五层。它们分别是: 内核层 Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动。硬件抽象层 该层为硬件厂商定义了一套标准的接口。这样可以在不影响上层…...
Tomcat学习进阶
目录 Apache Tomcat架构配置线程模型Tomcat 的类加载机制类加载器层次结构类加载流程 Tomcat 的优化策略Tomcat 的集群部署Tomcat故障排查 Apache Tomcat 架构配置 Apache Tomcat是一个开源的Java Servlet容器和Web服务器,它实现了Java EE规范中的Servlet和JSP API。…...
【C++】————智能指针
作者主页: 作者主页 本篇博客专栏:C 创作时间 :2024年8月20日 一,什么是智能指针 在C中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针&…...
GT IP中CC序列(Clock Correction Sequence)的周期性
CC序列(Clock Correction Sequence),即时钟校正序列,在数字通信中扮演着至关重要的角色。这一序列的周期性插入机制,旨在确保发送器和接收器之间的时钟同步,从而维持数据传输的准确性和稳定性。以下是CC序列…...
grafana pod 无法启动 Only one datasource per organization can be marked as default
标题信息 helm 部署的 prometheus 全栈监控 chart 为 prometheus-community/kube-prometheus-stack helm 部署的 loki 日志系统 chart 为 grafana/loki-stack 问题描述 grafana pod 启动不了,查看该pod 日志报错如下 logger=provisioning t=2024-08-21T06:42:45.954318228…...
你是如何克服编程学习中的挫折感的?(-@-^-0-)
在编程学习中遇到挫折感是极为常见且正常的现象,因为编程往往涉及解决复杂问题、理解抽象概念以及不断试错的过程。 以下是一些建议,帮助你在面对挫折时调整心态,继续前行: 接受失败是成长的一部分:首先要认识到&#…...
大数据技术之Zookeeper(1)
目录 Zookeeper 入门 概述 Zookeeper的主要特点包括: Zookeeper的应用场景: Zookeeper的基本概念: 架构: Zookeeper工作机制 Zookeeper数据结构 Znode(Zookeeper Node) Znode的类型 Znode路径 Znode属性 Wa…...
鸿蒙学习(四):泛型空安全模块导入导出
泛型与函数 泛型类型和函数允许创建的代码在各种类型上运行,而不仅支持单一类型。 泛型类和接口(Element) 类和接口可以定义为泛型,将参数添加到类型定义中,如以下示例中的类型参数Element: class CustomStack<Element>…...
无人机(Unmanned Aerial Vehicle, UAV)视觉感知论文汇总
综述类 A Survey of Object Detection for UAVs Based on Deep LearningDeep Learning for UAV-based Object Detection and Tracking:A surveyMoving Target Tracking by Unmanned Aerial Vehicle:A Survey and TaxonomyVision-Based Learning for Dro…...
【ORACLE】 ORA-01691: Lob 段无法通过 8192 (在表空间 XXX_SPACE 中) 扩展
ORA-01691错误通常表示Oracle数据库在尝试扩展LOB段时无法为表空间分配更多的空间。这个问题通常由表空间容量不足引起。根据搜索结果,以下是几种可能的解决方案: 检查并扩大表空间:首先,确认表空间是否已经达到其最大容量。可以使…...
Java之静态代理与动态代理的区别
🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法 🔥 微信:zsqtcyw 联系我领取学习资料 …...
公司内网监控软件有哪些?(2024年10款最新款推荐内网监控软件)
在2024年,公司内网监控软件市场提供了多种选择,以满足不同企业的监控需求。 以下是一些值得推荐的最新款内网监控软件: 1. Performance Monitor 核心功能:不仅是一款局域网监控软件,更是一个全面的内网安全管理解决方…...
CUDA编程07 - 卷积的优化
一:概述 在接下来的几篇文章中,我们将讨论一组重要的并行计算模式。这些模式是许多并行算法的基础,这些算法出现在许多并行应用中。我们将从卷积开始,卷积是一种流行的数组操作,广泛应用于信号处理、数字录音、图像处理、视频处理和计算机视觉等领域。在这些应用领域中,卷…...
解锁高效办公新姿势:SSO单点登录+企业网盘完美搭配
在现代互联网环境中,随着企业业务的不断扩展,多系统、多应用的集成成为常态。为了提升用户体验,减少用户在不同系统间切换的繁琐,单点登录(SSO, Single Sign-On)技术应运而生。 本文将详细介绍SSO单点登录的…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
