跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ STL 容器详解:unordered_map 与 unordered_set 实战指南

C++ STL unordered_map 和 unordered_set 基于哈希表实现,提供 O(1) 平均查找效率。内容涵盖容器定义、构造方法、常用操作(插入、查找、删除)、自定义哈希函数及性能优化建议。通过对比 map/set 差异,解析实际开发中如何平衡有序性与性能,帮助开发者高效管理数据。

2177283801发布于 2026/3/26更新于 2026/6/1120 浏览
C++ STL 容器详解:unordered_map 与 unordered_set 实战指南

概念与区别

在 C++ 标准模板库(STL)中,unordered_map 和 unordered_set 是基于哈希表实现的关联容器。它们的核心优势在于摒弃了元素的有序性,从而换取了近乎常数时间的操作效率。

核心定义

  • unordered_map:存储键值对(key-value pairs)。底层采用哈希表,每个键唯一,平均查找、插入和删除的时间复杂度为 O(1)。
  • unordered_set:仅存储唯一元素,无键值对结构。同样基于哈希表,保证元素唯一性,查找效率极高。

与 map/set 的对比

虽然功能相似,但两者在实现机制上有显著差异:

  1. 底层结构:无序容器使用哈希表,有序容器(map/set)通常基于红黑树。
  2. 时间复杂度:无序容器平均 O(1),有序容器为 O(log N)。
  3. 元素顺序:无序容器不保证遍历顺序,有序容器保持升序排列。
  4. 迭代器类型:无序容器提供单向迭代器,有序容器支持双向迭代。
  5. 键的要求:无序容器需要键支持哈希和相等比较,有序容器需要键支持小于比较。

在实际开发中,若不需要维护顺序且追求极致性能,优先选择无序容器;若需区间查询或有序遍历,则保留有序容器。

构造方法

容器初始化方式灵活,支持多种场景。

unordered_map 构造

构造函数说明
unordered_map()默认构造空容器
unordered_map(InputIterator first, InputIterator last)区间初始化
unordered_map(const unordered_map& um)拷贝构造
unordered_map(std::initializer_list<value_type> il)初始化列表

示例:初始化列表与区间构造

#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;

int main() {
    // 初始化列表
    unordered_map<string, int> myMap = {{"apple", }, {, }};
    
    
    vector<pair<string, >> vec = {{, }, {, }};
    ;
    
     ( & pair : myMap) {
        cout << pair.first <<  << pair.second << endl;
    }
     ;
}
1
"banana"
2
// 区间构造
int
"apple"
1
"banana"
2
unordered_map<string, int> myMap2(vec.begin(), vec.end())
for
const
auto
": "
return
0

unordered_set 构造

用法类似,仅存储单一值。

#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;

int main() {
    unordered_set<int> mySet = {1, 2, 3, 4, 5};
    vector<int> vec = {1, 2, 3, 4, 5};
    unordered_set<int> mySet2(vec.begin(), vec.end());
    
    for (const auto& elem : mySet) {
        cout << elem << " ";
    }
    return 0;
}

常用操作

插入操作

insert() 是最通用的方法,而 emplace() 在构造复杂对象时更高效,因为它直接在容器内构建元素,避免了临时对象的复制开销。

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<int, string> myMap;
    
    // insert: 先构造再插入
    myMap.insert({1, "One"});
    
    // emplace: 直接构造,避免复制
    myMap.emplace(2, "Two");
    
    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl;
    }
    return 0;
}

查找操作

  • find():返回迭代器,若未找到返回 end()。
  • count():返回元素出现次数(对于 set/map 通常为 0 或 1)。
  • operator[]:仅适用于 map,查找失败时会自动插入默认值。
#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<int, string> myMap = {{1, "One"}, {2, "Two"}};
    
    // find
    auto it = myMap.find(2);
    if (it != myMap.end()) {
        cout << "Found: " << it->second << endl;
    }
    
    // count
    cout << "Count of 1: " << myMap.count(1) << endl;
    
    // operator[] 注意:会修改容器
    cout << "Value at key 3: " << myMap[3] << endl; // 自动插入 3 -> ""
    return 0;
}

删除操作

使用 erase() 删除指定元素或区间,clear() 清空所有数据。

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    unordered_set<int> mySet = {1, 2, 3, 4, 5, 6};
    
    // 删除单个元素
    mySet.erase(3);
    
    // 删除区间 [it1, it2)
    auto it1 = mySet.find(2);
    auto it2 = mySet.find(5);
    mySet.erase(it1, it2);
    
    // 清空
    mySet.clear();
    return 0;
}

高级用法:自定义哈希

当处理自定义类型(如结构体)时,默认哈希函数不可用,需显式提供。

unordered_map 自定义哈希

#include <iostream>
#include <unordered_map>
#include <functional>
using namespace std;

struct Point {
    int x, y;
    bool operator==(const Point& other) const {
        return x == other.x && y == other.y;
    }
};

// 自定义哈希结构体
struct PointHash {
    size_t operator()(const Point& p) const {
        return hash<int>()(p.x) ^ hash<int>()(p.y);
    }
};

int main() {
    unordered_map<Point, string, PointHash> pointMap;
    pointMap[{1, 2}] = "Point(1, 2)";
    pointMap[{3, 4}] = "Point(3, 4)";
    
    for (const auto& pair : pointMap) {
        cout << pair.second << endl;
    }
    return 0;
}

unordered_set 自定义比较

除了哈希,有时还需自定义相等判断逻辑。

#include <iostream>
#include <unordered_set>
#include <functional>
using namespace std;

struct Point {
    int x, y;
};

struct PointHash {
    size_t operator()(const Point& p) const {
        return hash<int>()(p.x) ^ hash<int>()(p.y);
    }
};

struct PointEqual {
    bool operator()(const Point& p1, const Point& p2) const {
        return p1.x == p2.x && p1.y == p2.y;
    }
};

int main() {
    unordered_set<Point, PointHash, PointEqual> pointSet;
    pointSet.insert({1, 2});
    pointSet.insert({3, 4});
    pointSet.insert({1, 2}); // 重复点不会插入
    
    cout << "Size: " << pointSet.size() << endl; // 输出 2
    return 0;
}

性能分析与优化

时间复杂度

操作平均复杂度最坏复杂度
插入/查找/删除O(1)O(N)
遍历O(N)O(N)

最坏情况通常由严重的哈希冲突引起。虽然概率极低,但在极端输入下仍需警惕。

空间与负载因子

容器内部维护桶(bucket)数组。负载因子(元素数/桶数)超过阈值(默认约 1.0)时会触发重新哈希(rehash),导致性能波动。

优化建议

  1. 预留空间:若已知元素数量,使用 reserve() 提前分配桶,减少 rehash 次数。
  2. 定制哈希:针对特定数据结构设计分布均匀的哈希函数,降低冲突率。
  3. 场景匹配:无需排序时用 unordered,需排序或范围查询时用 map/set。

总结

unordered_map 和 unordered_set 是 C++ 中处理高频查找与去重任务的首选工具。理解其哈希原理、掌握自定义哈希方法,并合理预估性能开销,能显著提升代码效率。在实际工程中,根据数据特性在有序性与速度之间做出权衡,才是关键所在。

目录

  1. 概念与区别
  2. 核心定义
  3. 与 map/set 的对比
  4. 构造方法
  5. unordered_map 构造
  6. unordered_set 构造
  7. 常用操作
  8. 插入操作
  9. 查找操作
  10. 删除操作
  11. 高级用法:自定义哈希
  12. unordered_map 自定义哈希
  13. unordered_set 自定义比较
  14. 性能分析与优化
  15. 时间复杂度
  16. 空间与负载因子
  17. 优化建议
  18. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 DeepSeek 和 Cursor 构建智能代码审查工具实战
  • Spring 动态代理详解
  • 延凡 AI 工业视觉分析算法平台技术架构与应用
  • Neo4j Aura Agent 正式上线:图谱驱动的智能体构建新范式
  • 前端无法获取响应头(如 Content-Disposition)的原因与解决方案
  • 医疗 AI 模型部署的现实困境与临床集成挑战
  • AI 中转 API 原理及低价背后的风险解析
  • 腾讯混元 Image 2.1 GGUF 版:消费级显卡本地部署方案
  • 前端直连模型 vs 完整 MCP:大模型驱动地图原理与实践
  • 2026 年 AI Agent 开发:10 个实战验证的设计模式
  • AI 编程实践:自动化代码生成、低代码开发与算法优化
  • HarmonyOS 5.0 物联网开发:基于星闪技术的智能家居边缘计算网关
  • MySQL 动态分区管理:自动化与优化实践
  • 纯 C# 自研轻量级跨平台 UI 引擎:内核 <200KB 与高性能渲染实践
  • 12 个程序员高含金量证书详解与职业价值分析
  • SDXL Prompt Styler 工具使用指南:优化 AI 绘画提示词
  • 贪心算法:674.最长连续递增序列
  • 图形管线与渲染引擎的 C++ 架构:模块化与跨平台实践
  • SpringBoot 省级旅游口号管理系统设计与实现
  • Python 异步编程实战:构建高性能网络应用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online