C++ STL容器 map
C++ STL容器 map 基本用法详解
map 是 C++ 标准模板库(STL)中的关联容器,存储的元素是 键值对(key-value pair),并根据 键(key)自动排序(默认按 key 升序)。map 的键是唯一的,不能重复。
1. 头文件与定义
#include <map>
#include <string>
using namespace std;
// 定义一个空的 map
map<int, string> m1; // key为int, value为string
map<string, double> priceMap; // key为string, value为double
2. 插入元素
使用 [] 运算符
最简单直接,如果键不存在则插入,存在则覆盖值。
m1[1] = "apple";
m1[2] = "banana";
m1[3] = "cherry";
使用 insert 函数
- 插入一个
pair - 如果键已存在,插入失败(不会覆盖原有值)
m1.insert(pair<int, string>(4, "date"));
m1.insert(make_pair(5, "elderberry"));
m1.insert({6, "fig"}); // C++11 初始化列表
使用 emplace (C++11,更高效)
直接在容器内构造元素,避免拷贝。
m1.emplace(7, "grape");
3. 访问元素
使用 [] 运算符
如果键不存在,会自动插入一个使用默认值构造的元素。
cout << m1[2] << endl; // 输出: banana
cout << m1[8] << endl; // key=8 不存在,自动插入空字符串,输出空
使用 at() 函数(推荐)
带边界检查,若键不存在会抛出 std::out_of_range 异常。
try {
cout << m1.at(3) << endl; // 输出: cherry
cout << m1.at(9) << endl; // 抛出异常
} catch (const out_of_range& e) {
cout << "Key not found!" << endl;
}
使用 find 查找
返回迭代器,若未找到返回 end()。
auto it = m1.find(2);
if (it != m1.end()) {
cout << "Found: " << it->second << endl;
} else {
cout << "Not found" << endl;
}
4. 删除元素
| 方法 | 说明 |
|---|---|
erase(key) | 删除键为 key 的元素,返回删除个数(map中为0或1) |
erase(iterator) | 删除迭代器指向的元素 |
erase(first, last) | 删除区间 [first, last) 内的元素 |
clear() | 清空整个 map |
m1.erase(3); // 删除 key=3 的元素
auto it = m1.find(4);
if (it != m1.end()) {
m1.erase(it); // 通过迭代器删除
}
m1.clear(); // 清空
5. 遍历 map
使用迭代器
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); ++it) {
cout << "Key: " << it->first << ", Value: " << it->second << endl;
}
C++11 范围 for 循环(推荐)
for (const auto& pair : m1) {
cout << pair.first << " => " << pair.second << endl;
}
C++17 结构化绑定(更清晰)
for (const auto& [key, value] : m1) {
cout << key << " : " << value << endl;
}
6. 常用成员函数
| 函数 | 作用 |
|---|---|
size() | 返回元素个数 |
empty() | 判断是否为空 |
count(key) | 返回某个键的出现次数(map中非0即1) |
lower_bound(key) | 返回第一个 key >= 给定键 的迭代器 |
upper_bound(key) | 返回第一个 key > 给定键 的迭代器 |
7. 自定义键的排序规则
默认使用 std::less<Key>(即 < 运算符)升序排列。可以通过指定比较函数或函数对象改变排序方式。
使用 greater 实现降序
map<int, string, greater<int>> descMap;
descMap[1] = "one";
descMap[2] = "two";
// 遍历顺序:2, 1
自定义比较函数(Lambda,C++11)
auto cmp = [](const string& a, const string& b) {
return a.length() < b.length(); // 按字符串长度升序
};
map<string, int, decltype(cmp)> strMap(cmp);
strMap["apple"] = 5;
strMap["kiwi"] = 4;
strMap["banana"]= 6;
8.二分查找:lower_bound(key)/upper_bound(key)
两个函数是典型的二分查找接口(返回迭代器,指向第一个 >= key 或 > key 的位置)。
// 查找第一个 key >= 2 的元素
auto it = ma.lower_bound(2);
if (it != ma.end()) {
cout << "lower_bound(2): " << it->first << " => " << it->second << endl;
}
// 查找第一个 key > 2 的元素
auto it2 = ma.upper_bound(2);
if (it2 != ma.end()) {
cout << "upper_bound(2): " << it2->first << " => " << it2->second << endl;
}
9.注意事项
map 默认只能通过 key 查找 value,如果想实现“根据 value 查找 key”,也有几种变通办法
- 直接遍历查找(简单但效率低,时间复杂度 O ( n ) O(n) O(n),适合小规模数据或偶尔查询。
- 使用反向映射(推荐,查询 O ( 1 ) O(1) O(1) 或 O ( l o g n ) O(log n) O(logn))
- 如果经常需要双向查找,可以手动维护一个反向 map。
- 假设 value 也是唯一的(否则反向映射无法处理重复值)。
- 更新原始 map 时,同步更新反向 map。
10. 完整示例代码
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> fruitCount;
// 插入
fruitCount["apple"] = 10;
fruitCount["banana"] = 5;
fruitCount.insert({"orange", 8});
fruitCount.emplace("grape", 12);
// 访问与修改
fruitCount["apple"] += 2;
cout << "Apple count: " << fruitCount.at("apple") << endl;
// 查找
string target = "banana";
auto it = fruitCount.find(target);
if (it != fruitCount.end()) {
cout << target << " found, count = " << it->second << endl;
}
// 遍历
cout << "\nAll fruits:" << endl;
for (const auto& [name, count] : fruitCount) {
cout << name << " => " << count << endl;
}
// 删除
fruitCount.erase("orange");
// 大小
cout << "\nTotal fruit types: " << fruitCount.size() << endl;
return 0;
}
11. 小结
| 特性 | 说明 |
|---|---|
| 底层实现 | 红黑树(自平衡二叉搜索树) |
| 元素顺序 | 按键自动排序 |
| 查找/插入/删除 | 时间复杂度 O(log n) |
| 键唯一性 | 键不允许重复,重复插入会覆盖或失败 |
| 适用场景 | 需要按键排序、快速查找、键唯一关联数据 |
9062

被折叠的 条评论
为什么被折叠?



