C++ STL map 系列全方位解析
·
map 系列是 C++ STL 中基于键值对(key-value)的关联容器,核心作用是通过唯一的 key 快速查找、存取对应的 value,是开发中最常用的容器之一。
本文会覆盖 std::map、std::multimap、std::unordered_map、std::unordered_multimap 四大核心容器,从底层原理、用法、区别、实战场景全方位讲解。
一、map 系列核心概念
1. 核心定义
- 存储形式:键值对(pair<key, value>),key 是索引,value 是存储的数据
- 核心能力:按键查找(而非按位置),时间复杂度远低于数组 /vector
- 分类标准:
- key 是否允许重复(map/multimap)
- 底层是否有序(有序 map / 无序 unordered_map)
2. 四大容器总览
表格
| 容器 | 底层结构 | key 唯一性 | 有序性 | 查找效率 | 适用场景 |
|---|---|---|---|---|---|
std::map |
红黑树 | 唯一 | 按键升序 | O(log n) | 需要有序 + 唯一 key |
std::multimap |
红黑树 | 可重复 | 按键升序 | O(log n) | 需要有序 + 重复 key |
std::unordered_map |
哈希表 | 唯一 | 无序 | O (1) 平均 | 追求极致查找速度 |
std::unordered_multimap |
哈希表 | 可重复 | 无序 | O (1) 平均 | 追求速度 + 允许重复 key |
核心结论:
- 要有序 → 选红黑树系列(map/multimap)
- 要最快查找 → 选哈希表系列(unordered_map)
- key 不能重复 → 不带
multi前缀- key 可以重复 → 带
multi前缀
二、std::map(有序唯一键值对)
1. 底层与特性
- 底层:红黑树(自平衡二叉搜索树)
- 特性:key 唯一、默认按键升序排列、插入 / 删除 / 查找稳定 O (log n)
- 头文件:
#include <map>
2. 基础用法(最常用)
cpp
运行
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
// 1. 定义:map<key类型, value类型>
map<int, string> student;
// 2. 插入数据(3种方式)
student[1001] = "张三"; // 最常用:数组式赋值(key不存在则创建)
student.insert({1002, "李四"}); // insert 插入 pair
student.insert(make_pair(1003, "王五"));
// 3. 访问数据
cout << "学号1001:" << student[1001] << endl; // 直接用key访问
// 安全访问:避免key不存在时自动创建空元素
auto it = student.find(1002);
if (it != student.end()) {
cout << "学号1002:" << it->second << endl;
}
// 4. 遍历(迭代器/范围for)
cout << "\n全部学生(有序):" << endl;
for (auto& pair : student) {
cout << "key:" << pair.first << ",value:" << pair.second << endl;
}
// 5. 删除元素
student.erase(1003); // 按key删除
// student.erase(it); // 按迭代器删除
// 6. 常用方法
cout << "\n元素个数:" << student.size() << endl;
cout << "是否为空:" << student.empty() << endl;
student.clear(); // 清空所有元素
return 0;
}
3. 核心方法速查
表格
| 方法 | 作用 |
|---|---|
map[k] = v |
赋值 / 访问(key 不存在会自动创建) |
insert({k,v}) |
插入键值对(key 重复则插入失败) |
find(k) |
查找 key,返回迭代器(找不到返回 end ()) |
erase(k) |
删除指定 key 的元素 |
size() |
返回元素个数 |
empty() |
判断是否为空 |
clear() |
清空容器 |
count(k) |
统计 key 出现次数(map 中只能是 0/1) |
三、std::multimap(有序可重复键值对)
1. 特性
- 与
map唯一区别:key 可以重复 - 有序、底层红黑树,不支持
[]运算符(因为 key 不唯一,无法直接索引) - 适用场景:一个 key 对应多个 value(如:一个班级对应多个学生)
2. 核心用法
cpp
运行
#include <map>
#include <iostream>
using namespace std;
int main() {
multimap<string, int> score; // 科目-分数(一个科目可多次录入)
// 插入重复key
score.insert({"数学", 90});
score.insert({"语文", 85});
score.insert({"数学", 95}); // key重复,允许插入
// 遍历:重复key会相邻排列
for (auto& p : score) {
cout << p.first << ":" << p.second << endl;
}
// 查找指定key的所有值(重点)
auto range = score.equal_range("数学");
cout << "\n数学所有分数:";
for (auto it = range.first; it != range.second; ++it) {
cout << it->second << " ";
}
return 0;
}
3. 专属方法
equal_range(k):返回 key 对应的所有元素的迭代器区间count(k):返回 key 重复的次数- 不支持
[]运算符!
四、std::unordered_map(无序唯一键值对)
1. 底层与特性
- 底层:哈希表(散列表)
- 特性:key 唯一、无序、平均查找 O (1)(效率远高于 map)
- 缺点:占用内存稍大、无顺序、极端情况(哈希冲突)退化为 O (n)
- 头文件:
#include <unordered_map>
2. 用法(与 map 几乎一致)
cpp
运行
#include <unordered_map>
#include <iostream>
using namespace std;
int main() {
unordered_map<int, string> dict;
// 插入、访问、遍历用法和map完全相同
dict[1] = "apple";
dict[2] = "banana";
// 遍历:无序输出(顺序不固定)
for (auto& p : dict) {
cout << p.first << ":" << p.second << endl;
}
return 0;
}
3. 与 map 的核心区别
- 效率:unordered_map 查找 / 插入更快(O (1) vs O (log n))
- 顺序:map 有序,unordered_map 无序
- 内存:哈希表内存占用更高
- key 要求:map 支持自定义 key(需重载 <),unordered_map 自定义 key 需提供哈希函数
五、std::unordered_multimap(无序可重复键值对)
- 组合特性:哈希表 + 无序 + key 可重复
- 用法:和
multimap一致,只是无序、效率更高 - 不支持
[]运算符,用equal_range查找重复 key
六、map 系列高频面试点 & 避坑指南
1. 高频面试问题
- map 和 unordered_map 的区别?底层(红黑树 / 哈希表)、有序性、效率、内存、适用场景
- 为什么 map 是有序的?底层红黑树会自动按键排序
- multimap 为什么不能用 []?key 不唯一,无法确定返回哪个 value
- map 插入重复 key 会发生什么?
map[key] = v会覆盖旧值;insert会插入失败
2. 开发避坑
- 不要用 [] 查找 map 元素
if (map[100])会自动创建 key=100 的空元素,导致容器体积变大✅ 正确写法:用find()或count() - multimap/unordered_multimap 禁止使用 []
- 自定义类型作为 key
- map:需要重载 < 运算符
- unordered_map:需要提供哈希函数 + 相等判断
- 性能选择
- 数据量小、需要有序 → map
- 数据量大、追求速度 → unordered_map
- 需要重复 key → 对应 multi 版本
七、实战选择建议
- 90% 业务场景:用
unordered_map(最快、唯一 key) - 需要排序展示 / 遍历:用
map(如排行榜、字典序输出) - 一对多数据:用
multimap/unordered_multimap - 嵌入式 / 内存紧张:优先
map(内存占用低)
总结
- map 系列是键值对存储,核心是按键快速查找
- 四大容器:有序唯一 (map)、有序重复 (multimap)、无序唯一 (unordered_map)、无序重复 (unordered_multimap)
- 底层决定特性:红黑树 = 有序稳定,哈希表 = 超快查找
- 开发首选:
unordered_map(效率优先),需要有序则用map
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)