C++ 模板库map数据结构的概念和使用案例
C++ std::map
概念详解
std::map
是 C++ 标准模板库(STL)中的一种关联容器,以键值对(Key-Value Pair)的形式存储元素,并根据键(Key)自动排序。其核心特性如下:
核心特性
- 有序性
元素按键的升序自动排序(默认使用std::less<Key>
,可通过比较器自定义)。 - 唯一键
每个键在map
中必须唯一(重复插入会失败)。 - 底层实现
通常基于红黑树(自平衡二叉搜索树),保证插入、删除、查找操作的时间复杂度为 O(log n)。 - 键不可变性
元素的键为常量(不可修改),值可修改。
基本操作与常用成员函数
操作 | 函数 | 示例 |
---|---|---|
插入元素 | insert() / emplace() | m.insert({"Alice", 90}); |
访问元素 | operator[] / at() | m["Bob"] = 85; |
查找元素 | find() | auto it = m.find("Charlie"); |
删除元素 | erase() | m.erase("Alice"); |
检查容器大小 | size() / empty() | if (!m.empty()) {...} |
遍历容器 | 迭代器 / 范围循环 | for (const auto& p : m) {...} |
使用案例:学生成绩管理系统
#include <iostream>
#include <map>
#include <string>int main() {// 创建map:键=学生姓名(string), 值=分数(int)std::map<std::string, int> scores;// 插入数据(3种方式)scores["Alice"] = 90; // 使用 operator[]scores.insert({"Bob", 85}); // 使用 insert + 初始化列表scores.emplace("Charlie", 95); // 使用 emplace(直接构造)// 尝试插入重复键(失败)auto ret = scores.insert({"Alice", 100});if (!ret.second) {std::cout << "Insert failed: Alice already exists.\n";}// 更新分数(通过键直接修改值)scores["Bob"] = 88; // Bob的分数更新为88// 安全访问(避免意外插入新键)std::cout << "Charlie's score: "<< (scores.find("Charlie") != scores.end() ? scores.at("Charlie") : -1)<< "\n";// 删除学生scores.erase("Alice");// 遍历并打印所有学生成绩(自动按姓名升序排序)std::cout << "\nCurrent Scores:\n";for (const auto& [name, score] : scores) { // C++17结构化绑定std::cout << name << ": " << score << "\n";}// 检查是否存在键std::string target = "David";if (scores.count(target)) {std::cout << target << " found.\n";} else {std::cout << target << " not found.\n";}return 0;
}
输出结果:
Insert failed: Alice already exists.
Charlie's score: 95Current Scores:
Bob: 88
Charlie: 95
David not found.
关键注意事项
- 避免
operator[]
的副作用
使用map[key]
访问不存在的键时,会自动插入该键(值初始化为0)。推荐先用find()
或count()
检查键是否存在。 - 自定义排序规则
可通过传递比较器实现降序排序:std::map<std::string, int, std::greater<>> scores; // 按键降序
- 性能考量
- 适合需要有序遍历的场景。
- 若只需检查键是否存在且不要求顺序,可用
std::unordered_map
(哈希表实现,O(1) 平均复杂度)。
应用场景
- 字典/配置文件解析(键值映射)
- 缓存机制(如LRU Cache,需结合链表)
- 需要有序键值对的任何场景