【C + +】unordered_set 和 unordered_map 的用法、区别、性能全解析 - 实践

news/2025/11/19 19:42:06/文章来源:https://www.cnblogs.com/ljbguanli/p/19243779

【C + +】unordered_set 和 unordered_map 的用法、区别、性能全解析 - 实践

个人主页:第七序章

专栏系列:C++

目录

❄️前言:

☀️一、unordered_set 和 unordered_map 简介

☀️二、 unordered_set 的基本用法

⭐2.1 基本操作

⭐2.2 解释

⭐2.3 unordered_set和set的区别

☀️三、unordered_map 的基本用法

⭐3.1 基本操作

⭐3.2 解释

⭐3.3 unordered_map和map的区别

☀️四、性能分析

☀️五、unordered_multimap和unordered_multiset

☀️六、本文小结

共勉:


❄️前言:

上一篇我们学习了基于红黑树封装的Map与Set今天我们来学习一下unordered_set和unordered_map。

☀️一、unordered_set 和 unordered_map 简介

在 C++ 标准库中,unordered_set和 unordered_map 都属于 无序关联容器。它们与set和 map 的主要区别在于,它们使用 哈希表 作为底层数据结构,因此它们的元素并不是按照某种顺序存储的,而是根据元素的哈希值存储。哈希表的查找效率通常是常数时间复杂度 O(1),但最坏情况下是 O(n)

  • unordered_set:是一个无序的集合容器,只存储唯一的元素,类似于set,但是内部没有元素的顺序。
  • unordered_map:是一个无序的映射容器,存储键值对,每个键唯一,类似于map,但是不保证按键的顺序排列。

更多详细内容可以参考文档unordered_set 和unordered_map 

☀️二、 unordered_set 的基本用法

unordered_set是一个存储唯一元素的集合,其中元素按哈希值进行存储。常用操作包括插入元素、删除元素、查找元素等。

  • unordered_set声明如下,Key就是unordered_set底层关键字的类型
  • unordered_set默认要求Key可以转化为整形,如果不支持或者有自己的需求的需要自己实现仿函数(Key转化为整形)传给第二个模版参数。
  • unordered_set底层存储数据的内存都是从空间适配器中申请的,如果自己有需求实现内存池,要传给第四个模版参数
  • 一般我们在使用的时候不需要传后三个模版参数。
  • unordered_set底层是使用哈希桶实现的,查找的效率为O(1);但是数据不再有序,所以取名为unordered_set

⭐2.1 基本操作

#include 
#include 
using namespace std;
void test_unordered_set()
{// 创建一个 unordered_setunordered_set uset;// 插入元素uset.insert(10);uset.insert(20);uset.insert(30);uset.insert(40);// 输出所有元素cout << "unordered_set contains: ";for (const auto& e : uset) {cout << e << " ";}cout << endl;// 查找if (uset.find(20) != uset.end())cout << "Found 20 in the unordered_set!" << endl;elsecout << "20 not found in the unordered_set!" << endl;// 删除元素uset.erase(30);cout << "After erasing 30, unordered_set contains: ";for (const auto& e : uset)cout << e << " ";cout << endl;// 判断是否为空if (uset.empty())cout << "The unordered_set is empty." << endl;elsecout << "The unordered_set is not empty." << endl;
}
int main() {test_unordered_set();return 0;
}

运行结果:

unordered_set contains: 10 20 30 40
Found 20 in the unordered_set!
After erasing 30, unordered_set contains: 10 20 40
The unordered_set is not empty.

⭐2.2 解释

  • insert():向 unordered_set中插入元素。插入的元素是唯一的,如果尝试插入重复元素,unordered_set 会忽略它。
  • find()用于查找元素。如果找到,返回指向该元素的迭代器;否则返回 end()
  • erase()用于删除指定元素。
  • empty():检查集合是否为空。

这里对于其他的函数,就需要去了解它底层的哈希桶结构了,在实现哈希结构时再去深入探究。

⭐2.3 unordered_set和set的区别

通过查看文档已经使用unoedered_set,我们可以发现unordered_setset支持的增删查改是一模一样的,我们现在就来看一下它们有什么不同:

  • 首先set的底层是红黑树,而unordered_set底层是哈希表。
  • 其次它们对于key的要求不同,set要求key支持比较;而unoedered_set要求key支持转化成整型且要支持比较。
  • 然后就是迭代器的不同,setiterator双向迭代器,而unordered_setiterator单向迭代器set底层是红黑树set的迭代器是有序+去重的;而unoedered_set底层是哈希桶unoedered_set无序+去重的。
  • 最后就是性能上的差异,对于大多数场景下unoedered_set增删查改的效率要高于set的;(红黑树的效率是O(log N),哈希表的效率是O(1)

至于其中细节上的不同,要了解了unordered_set的底层哈希表,才能真正理解

☀️三、unordered_map 的基本用法

unordered_map是一个哈希表实现的键值对容器,类似于map但是它的元素不按键排序。

unordered_mapunordered_set都是用哈希表进行封装实现的,这里就不过多描述了,和unordered_set十分相似。

⭐3.1 基本操作

#include 
#include 
using namespace std;
void test_unordered_map()
{//创建一个 unordered_mapunordered_map umap;//和map的operator[]一样,可以用来插入数据umap["apple"] = 2;umap["banana"] = 5;umap["orange"] = 3;//输出cout << "unordered_map contains:" << endl;for (const auto& pair : umap) {cout << pair.first << ": " << pair.second << endl;}//查找auto it = umap.find("banana");if (it != umap.end())cout << "Found 'banana' with value " << it->second << endl;elsecout << "'banana' not found in the unordered_map!" << endl;//删除umap.erase("orange");cout << "After erasing 'orange', unordered_map contains:" << endl;for (const auto& pair : umap)cout << pair.first << ": " << pair.second << endl;// 检查是否存在某个keyif (umap.count("apple") > 0)std::cout << "'apple' exists in the unordered_map." << std::endl;
}
int main() {test_unordered_map();return 0;
}

运行结果:

unordered_map contains:
apple: 2
banana: 5
orange: 3
Found 'banana' with value 5
After erasing 'orange', unordered_map contains:
apple: 2
banana: 5
"apple" exists in the unordered_map.

⭐3.2 解释

  • 插入元素:unordered_map 支持通过下标([])或者insert()插入元素。若键已存在,通过下标访问时会更新其对应的值。
  • find()查找给定键是否存在,返回指向该元素的迭代器,如果元素不存在,返回 end()
  • erase()删除指定键值对。
  • count()检查容器中是否存在指定的键。

⭐3.3 unordered_map和map的区别

这里setmap都是使用红黑树封装实现的,而unordered_setunordered_map都是使用哈希表封装实现的。

unordered_mapmap的区别与unordered_setset的区别是大差不差的。

  • 首先map的底层是红黑树,而unordered_map底层是哈希表
  • 其次它们对于key的要求不同,map要求key支持比较;而unoedered_map要求key支持转化成整型且要支持比较。
  • 然后就是迭代器的不同,mapiterator是双向迭代器,而unordered_mapiterator是单向迭代器;map底层是红黑树map的迭代器是有序+去重的;而unoedered_map底层是哈希桶unoedered_map无序+去重的。
  • 最后就是性能上的差异,对于大多数场景下unoedered_map增删查改的效率要高于map的;(红黑树的效率是O(log N),哈希表的效率是O(1)

☀️四、性能分析

这一部分,我们要学习底层哈希表以后才会深入理解;这里简单说一下

底层的哈希表使用的是哈希桶结构就是顺序表中存储链表,这样可以避免冲突的问题)。

unordered_set 和unordered_map的查找、插入和删除操作平均时间复杂度为O(1)。不过,由于哈希冲突的存在,最坏情况下时间复杂度会退化为O(n),即所有元素都映射到同一个哈希桶中。

  • 哈希冲突为了减少哈希冲突,C++ 中的 unordered_setunordered_map 使用了哈希表和动态扩展机制,使得哈希表的负载因子保持在合理范围内,避免性能急剧下降。
  • 负载因子容器的负载因子是元素数量与桶数量的比值,当负载因子达到某个阈值时,容器会自动增加桶的数量,从而保持查找效率。

☀️五、unordered_multimap和unordered_multiset

  • unordered_multimap/unordered_multisetmultimap/multiset功能完全类似,支持key冗余

☀️六、本文小结

类别unordered_setunordered_map
简介无序集合容器,存储唯一元素,底层为哈希表,元素无序无序映射容器,存储键值对(键唯一),底层为哈希表,元素无序
基本操作- 插入:insert()(忽略重复元素)- 查找:find()(返回迭代器,未找到返回end())- 删除:erase()- 判空:empty()- 插入:[](键存在则更新值)、insert()- 查找:find()(返回迭代器)- 删除:erase()- 检查键存在:count()
与对应有序容器区别set的区别:1. 底层:哈希表 vs 红黑树2. 键要求:支持转为整型且可比较 vs 仅需支持比较3. 迭代器:单向 vs 双向;元素无序 vs 有序4. 性能:增删查改平均 O (1) vs O (log N)map的区别:1. 底层:哈希表 vs 红黑树2. 键要求:支持转为整型且可比较 vs 仅需支持比较3. 迭代器:单向 vs 双向;元素无序 vs 有序4. 性能:增删查改平均 O (1) vs O (log N)
性能特性平均时间复杂度 O (1)(查找、插入、删除),最坏 O (n)(哈希冲突严重时)平均时间复杂度 O (1)(查找、插入、删除),最坏 O (n)(哈希冲突严重时)
相关扩展容器unordered_multiset:支持键冗余,功能类似multisetunordered_multimap:支持键冗余,功能类似multimap

共勉:

以上就是本篇博客的所有内容,如果你觉得这篇博客对你有帮助的话,可以点赞收藏关注支持一波~~


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/970327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI 代码分析(一)--工程结构

Spring AI 工程分析文档 请关注微信公众号:阿呆-bot 1. 工程结构概览 Spring AI 是一个大型的多模块 Maven 项目,采用模块化设计,主要分为核心模块、模型实现、向量存储、自动配置等几大类。下面我们来看看主要的目…

Spring Boot迅速集成MiniMax、CosyVoice实现文本转语音

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Cursor接入飞书MCP

痛点 以往cursor都没办法读取prd中的内容,然后都需要⼈⼯提炼出来喂给他,就导致效率⽐较低下;同时 ⼈⼯阅读prd难免会有疏漏,就导致往往review prd的时候才发现功能点遗漏或者理解错误。 希望能让cursor直接阅读pr…

完整教程:微信生态新机遇:视频号推客模式助力商家突围

完整教程:微信生态新机遇:视频号推客模式助力商家突围2025-11-19 19:35 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; …

linux framework

“Linux framework”通常指的是基于 Linux 内核构建的系统架构或软件框架,用于开发和管理 Linux 系统。它包括以下几个关键部分:1. Linux 内核(Kernel)作用:管理硬件资源、进程调度、内存管理、文件系统等。 关键…

Spring AI 代码分析(二)--Model 领域

Spring AI Model 领域划分分析 请关注微信公众号:阿呆-bot 1. 工程结构概览 spring-ai-model 是 Spring AI 的核心抽象模块,它定义了所有 AI 模型能力的统一接口。从 DDD(领域驱动设计)的角度来看,这个模块清晰地…

gdb实践((2510更新)

GCC/gcc/g++那些事儿 掌握gdb调试从入门到进阶(一) GDB 调试 - 从入门实践到原理 GDB调试从基础到精通实例 常用gdb命令 n:单步调试 step <count>:单步跟踪,如果有函数调用,他会进入该函数。 finish:运行…

Mars项目与TensorFlow集成指南

Mars项目与TensorFlow集成指南Mars项目与TensorFlow集成指南Mars项目与TensorFlow集成指南 概述 Mars是一个基于张量的统一大规模数据计算框架,能够无缝扩展NumPy、Pandas、Scikit-learn等库的计算能力。与TensorFlow…

win10/win11系统默认应用或文件打开方式重启后被自动重置的解决办法

起因 最近在电脑重启后,系统的默认浏览器,一切格式的文件默认打开方式(.zip .pdf .txt)都被系统重置了。即使我重新设置了默认浏览器及文件的默认打开,重启后依然被重置,这让我非常恼火。多次询问AI及搜索后依然…

详细介绍:第八节_PySide6基本窗口控件_按钮类控件(QAbstractButton)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

哪里有免费的编程体验课?2025国内外优质平台与真实体验价值分析

哪里有免费的编程体验课?2025国内外优质平台与真实体验价值分析过去几年,“免费编程体验课”成了家长和开发者圈子里都会碰到的话题。 资源不少,但质量落差极大:有些是真课,有些则更像“试用版 PPT 宣讲”。 这篇…

2025 上海办公室 商铺装修核心服务商 TOP5 解析报告:双场景适配能力与品质选型全景指南

2025 上海办公室 & 商铺装修核心服务商 TOP5 解析报告:双场景适配能力与品质选型全景指南针对 “上海办公室商铺装修找哪家强?” 这一问题,我将聚焦两大核心场景,先拆解用户选品痛点与权威评估标准,再结合 TO…

Luogu P6234 [eJOI 2019] T 形覆盖 题解 [ 紫 ] [ 图论建模 ] [ 分类讨论 ] [ 基环树 ]

T 形覆盖 场上没有注意到转化,对着基环树和树的部分暴力图论建模,爆肝 3h 大分讨以 7.88KB 的代码成功通过。 Sol.1 暴力分讨 下文中,我们称 T 形的中心为黑点,其余格子为白点。 从部分分做法开始想,当 \(\min di…

gemini3-思考模式 测评

8米长的竹竿能否通过高4米宽3米的门? ---》能,立体的情况下可以通过 gemini3 ---》 成功可以使用任何数字符号,但不能改变数字位置,怎样让这个等式成立: 6 5 4 1 = 24 ---》 6 / (5/4 -1 ) = 24 或者 (6−5)!4!1=2…

AI Compass前沿速览:Gemini 3、Grok 4.1、GPT-5.1、千问、Lumine-3D开世界AI智能体

AI Compass前沿速览:Gemini 3、Grok 4.1、GPT-5.1、千问、Lumine-3D开世界AI智能体AI Compass前沿速览:Gemini 3、Grok 4.1、GPT-5.1、千问、Lumine-3D开世界AI智能体 AI-Compass 致力于构建最全面、最实用、最前沿的…

人工智能之编程进阶 Python高级:第八章 网络并发类模块

人工智能之编程进阶 Python高级:第八章 网络并发类模块人工智能之编程进阶 Python高级 第八章 网络并发类模块@目录人工智能之编程进阶 Python高级前言1. TCP 服务端(监听连接)2. TCP 客户端3. UDP 示例(无连接)�…

2025CCPC济南站游记

Day -1 不想学文化课。 Day 0 在车上颓。 队友落在烟台了,下午热身赛可能要单打。 学校午饭不错啊,吃了30元,剩下餐券换成饮料了。吃的烤肉拌饭+羊肉泡馍。为啥我觉得羊肉泡馍不如直接喝羊汤好喝。 下午1点到酒店,…

ssh登录报错Permission denied(publickey,gssapi-keyex,gssapi-with-mic,password

ssh 密码登录报错Permission denied(publickey,gssapi-keyex,gssapi-with-mic,password) 当我启动一个虚拟机,想要像往常一样使用密码登录的时候, sshpass -p 123456 ssh -o StrictHostKeyChecking=no root@127.0.0.…

Bisq交易协议全解析:从多签到MuSig的技术演进

本文深入解析Bisq去中心化交易所的交易协议技术架构,涵盖多签协议演进、MuSig加密方案、闪电网络集成等核心技术,详细介绍了各代协议的安全模型和隐私保护机制,以及未来路线图中的跨链原子交换等创新功能。Bisq交易…

十六岁的断章

不知道标题该写什么,就这样吧。 没有人理解我。免责声明 本文由 AI 辅助创作,如有雷同,纯属巧合。周日争执 我不知道该从何写起,但确实,我已经无计可施。 下面的对话是我凭记忆概括的,具体措辞已不太清晰。 那天…