C++中的map容器详解
1. map概述
map是C++ STL中的关联容器,它存储**键值对(key-value)**并按key自动排序。map基于红黑树实现,提供高效的查找、插入和删除操作。
2. 基本特性
- 唯一键值:每个key只能出现一次
- 自动排序:元素总是按key排序
- 高效查找 :基于key的查找时间复杂度为O(log2n)O(\log_2 n)O(log2n)
- 键不可修改 :key是
const的,value可以修改
3. 头文件与声明
cpp
#include <map>
using namespace std;
map<int, string> m1; // 空map,key为int,value为string
map<string, int, greater<string>> m2; // 空map,按key降序排列
map<string, int> m3 = {{"Alice", 25}, {"Bob", 30}}; // 初始化列表
4. 构造函数与初始化
4.1 默认构造
cpp
map<string, double> m; // 创建空map
4.2 范围构造
cpp
pair<string, int> arr[] = {{"A", 1}, {"B", 2}};
map<string, int> m(arr, arr+2); // 用数组范围构造
4.3 拷贝构造
cpp
map<string, int> m2(m1); // 拷贝构造
5. 容量操作
5.1 size()
cpp
cout << m.size(); // 返回元素数量
5.2 empty()
cpp
if(m.empty()) {
cout << "Map is empty";
}
5.3 max_size()
cpp
cout << m.max_size(); // 返回map可容纳的最大元素数
6. 元素访问
6.1 operator[]
cpp
m["Alice"] = 25; // 插入或修改元素
int age = m["Bob"]; // 访问元素(如果不存在会插入默认值)
6.2 at()
cpp
int age = m.at("Alice"); // 访问元素(如果不存在抛出out_of_range异常)
7. 修改操作
7.1 insert()
cpp
m.insert({"Charlie", 28}); // 插入单个元素
m.insert(make_pair("David", 32)); // 使用make_pair
m.insert({{"Eve", 27}, {"Frank", 40}}); // 插入多个元素
7.2 emplace()
cpp
m.emplace("Grace", 35); // 原地构造元素,比insert更高效
7.3 erase()
cpp
m.erase("Alice"); // 删除指定key的元素
m.erase(m.begin()); // 删除迭代器指向的元素
m.erase(m.begin(), m.find("Bob")); // 删除范围元素
7.4 clear()
cpp
m.clear(); // 清空所有元素
7.5 swap()
cpp
map<string, int> m2;
m.swap(m2); // 交换两个map的内容
8. 查找操作
8.1 find()
cpp
auto it = m.find("Alice"); // 查找元素,返回迭代器
if(it != m.end()) {
cout << "Found: " << it->first << " => " << it->second;
}
8.2 count()
cpp
if(m.count("Bob")) { // 返回匹配key的数量(0或1)
cout << "Key exists";
}
8.3 lower_bound() & upper_bound()
cpp
auto lb = m.lower_bound("B"); // 返回第一个不小于"B"的元素的迭代器
auto ub = m.upper_bound("D"); // 返回第一个大于"D"的元素的迭代器
8.4 equal_range()
cpp
auto range = m.equal_range("C"); // 返回等于"C"的元素范围
// range.first是lower_bound, range.second是upper_bound
9. 迭代器
9.1 begin() & end()
cpp
for(auto it = m.begin(); it != m.end(); ++it) {
cout << it->first << ": " << it->second << endl;
}
9.2 rbegin() & rend()
cpp
for(auto rit = m.rbegin(); rit != m.rend(); ++rit) {
cout << rit->first << ": " << rit->second << endl; // 反向遍历
}
10. 完整示例
cpp
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
// 创建并初始化map
map<string, int> ageMap = {{"Alice", 25}, {"Bob", 30}};
// 插入元素
ageMap.insert({"Charlie", 28});
ageMap.emplace("David", 32);
ageMap["Eve"] = 27; // 使用operator[]插入
// 修改元素
ageMap["Alice"] = 26; // 修改Alice的年龄
// 查找元素
if(ageMap.find("Bob") != ageMap.end()) {
cout << "Bob's age: " << ageMap["Bob"] << endl;
}
// 删除元素
ageMap.erase("Charlie");
// 遍历map
cout << "All entries:" << endl;
for(const auto& [name, age] : ageMap) { // C++17结构化绑定
cout << name << ": " << age << endl;
}
// 范围查询
cout << "Names between A and C:" << endl;
auto low = ageMap.lower_bound("A");
auto up = ageMap.upper_bound("C");
for(auto it = low; it != up; ++it) {
cout << it->first << ": " << it->second << endl;
}
// 容量信息
cout << "Size: " << ageMap.size() << endl;
cout << "Is empty: " << (ageMap.empty() ? "Yes" : "No") << endl;
return 0;
}
11. 自定义比较函数
cpp
struct CaseInsensitiveCompare {
bool operator()(const string& a, const string& b) const {
return strcasecmp(a.c_str(), b.c_str()) < 0;
}
};
map<string, int, CaseInsensitiveCompare> caseInsensitiveMap;
12. 性能提示
- 查找操作优先使用
find()而非operator[],避免意外插入 - 插入大量数据时,考虑预先构造
vector再转为map - 使用
emplace()替代insert()可避免不必要的拷贝 - 对于频繁查找但不需排序的场景,考虑使用
unordered_map