map容器
map 是 C++ STL 中最常用的有序关联式容器 ,核心是存储 key-value(键值对),且 key 唯一、自动排序,底层基于红黑树实现,保证增删查改的时间复杂度稳定在O(logn)。
特性:
- 存储结构:键值对(
key-value),每个key对应唯一value - 排序规则:默认按
key升序排列(可自定义排序规则) - 可修改性:
key不可修改(需删除后重新插入),value可直接修改 - 底层实现:红黑树(平衡二叉树),避免退化成链表,保证高效操作
- 空值处理:用
[]访问不存在的key时,会自动插入该key,value为默认值
基本使用
- 使用
map必须包含头文件
c++
#include <map> // 核心头文件
- 初始化
c++
// 1、空map(默认构造函数
// 键(int)值(string)
map<int, string> m1;
// key(可以是自定义类型)
map<pair<int, int>, vector<int>> m2;
// 2、列表初始化(c++ 11)
map<int, string> m3 = {
{1, "zs"},
{2, "ls"}
};
// 3、拷贝构造
map<int, string> m4(m3);
// 4、范围初始化
map<int, string> m5(m3.begin(), m3.end());
// 5、自定义键的排序规则
// 这里的排序规则只针对键,可以传入比较函数或者仿函数
map<int, string, greater<int>> m6;
核心操作API
插入元素
-
\]运算符,m\[key\] = value的方式,比较简单(key 不存在则插入,存在则修改 value);
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
// []插入元素
m[3] = "ww";
cout << m[3] << endl;
* insert({key, value}),key 存在则**插入失败**(不修改),返回 pair \<迭代器,bool\>
```c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
// insert插入元素
pair<map<int,string>::iterator, bool> ret = m.insert({ 3, "ww" });
cout << ret.second << endl; // 1
ret = m.insert({ 3, "zl" });
cout << ret.second << endl; // 0
emplace(key, value)原地构造,避免拷贝,性能优于 insert,key 存在则插入失败insert_or_assign(key, value)C++17 新增,key 存在则修改 value,不存在则插入(兼顾 [] 和 insert 的优点)
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
// insert_or_assign插入元素
m.insert_or_assign(3, "ww");
m.insert_or_assign(3, "ll");
cout << m[3] << endl; // ll
访问元素
-
\] 运算符,不建议使用(不存在则会插入默认值)
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
cout << m.at(2) << endl;
- 迭代器访问
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
cout << ret->first << ":" << ret->second << endl;
}
查找元素
- find,返回迭代器,如果未找到返回m.end()
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
cout << ret->first << ":" << ret->second << endl;
}
- count(),仅判断是否存在
删除元素
- 按key删除,返回删除元素的个数
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
int ret = m.erase(1);
cout << ret << endl; // 1
- 按迭代器删除
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
auto ret = m.find(1);
// 这里必须判断是否找到元素
if (ret != m.end())
{
// 返回的是迭代器
auto re = m.erase(ret);
cout << re->second << endl;
}
- 删除范围,左开右闭
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
m.erase(m.begin(), m.find(2));
- clear清空所有元素
遍历元素
- 普通迭代器,可读写
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
for (map<int, string>::iterator it = m.begin(); it!= m.end(); ++it)
{
cout << "key = " << it->first << ", value = " << it->second << endl;
}
- const迭代器,只读
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
for (map<int, string>::const_iterator it = m.cbegin(); it!= m.cend(); ++it)
{
cout << "key = " << it->first << ", value = " << it->second << endl;
}
- 范围for循环(c++11)
c++
map<int, string> m = {
{1, "zs"},
{2, "ls"}
};
for (auto& p : m)
{
cout << p.first << ": " << p.second << endl;
}
- 反向迭代器
进阶用法
- 自定义排序规则
- 按key降序
c++
map<int, string, greater<int>> m6;
- 自定义排序函数
c++
// 按照字符串长度排序(倒序)
struct strLenCmp {
bool operator()(const string& a, const string& b) const
{
return a.size() > b.size();
}
};
int main()
{
map<string, string, strLenCmp> m = {
{"aaa", "a"},
{"bbbb", "b"},
{"ccccc", "c"}
};
for (auto& p : m) {
cout << p.first << endl;
}
return EXIT_SUCCESS;
};
- 若 `key` 是自定义结构体 / 类,必须重载 `<` 运算符(满足排序规则)
- 性能优化
- 避免频繁使用 [] 访问不存在的 key(会自动插入默认值,浪费内存);
- 插入大量元素时,优先用 emplace() 而非 insert()(原地构造,减少拷贝);
- 遍历只读场景用 const 迭代器(避免误修改,且性能略优);
- 若无需有序,优先用 unordered_map(哈希表,平均查找 O(1))。
结束语
map核心是有序唯一键值对 ,底层红黑树保证 O(logn) 操作效率,默认按key升序排列;- 插入优先用
emplace()(高性能),访问优先用find()+ 迭代器(避免[]自动插入空值),删除用erase(key)(最直观); - 自定义
key需重载<运算符,自定义排序需传入仿函数,只读遍历用const迭代器更安全。