- C++
C++ map
- 2025-5-22 22:23:38 @
🗺️ C++ map
通俗易懂教程 | 快速掌握键值对存储!🚀
🎯 一、什么是 map?
在 C++ 中,map
是一种关联容器(Associative Container),用于存储 “键值对”(Key-Value Pair)。
你可以把它想象成一本字典:
单词(Key) | 含义(Value) |
---|---|
apple | 苹果 |
dog | 狗 |
在编程中,我们也可以这样写:
myMap["apple"] = "苹果";
myMap["dog"] = "狗";
🧱 二、C++ 标准库中的 map 特点
特性 | 描述 |
---|---|
存储结构 | 默认按 key 排序(升序) |
键的唯一性 | 每个 key 只能出现一次 |
支持快速查找 | 基于红黑树实现,查找效率高 |
头文件 | <map> |
使用方式 | using namespace std; (本教程统一使用) |
🔧 三、常用操作一览表 ✅
方法 | 功能说明 |
---|---|
map[key] = value |
添加或修改 key 对应的 value |
map.find(key) |
查找 key 是否存在 |
map.count(key) |
判断 key 是否存在(0 或 1) |
map.erase(key) |
删除指定 key 的键值对 |
map.size() |
返回 map 中键值对的数量 |
map.empty() |
判断是否为空 |
map.begin(), map.end() |
遍历 map 所需的迭代器 |
🧪 四、代码示例讲解 💻
✅ 示例 1:创建和添加元素
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, string> myMap;
// 添加键值对
myMap["apple"] = "苹果";
myMap["dog"] = "狗";
myMap["car"] = "汽车";
cout << "apple 的含义是:" << myMap["apple"] << endl;
return 0;
}
📌 输出:
apple 的含义是:苹果
✅ 示例 2:遍历 map(使用迭代器)
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, string> myMap;
myMap["apple"] = "苹果";
myMap["dog"] = "狗";
myMap["car"] = "汽车";
// 遍历 map
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
cout << it->first << " -> " << it->second << endl;
}
return 0;
}
📌 输出:
apple -> 苹果
car -> 汽车
dog -> 狗
✅ 示例 3:判断 key 是否存在
if (myMap.count("cat")) {
cout << "cat 存在" << endl;
} else {
cout << "cat 不存在" << endl;
}
✅ 示例 4:删除一个键值对
myMap.erase("dog");
📚 五、举个生活中的例子 💡
你正在开发一个学生管理系统,每个学生的学号是唯一的 key,姓名是对应的 value:
map<int, string> studentMap;
studentMap[1001] = "张三";
studentMap[1002] = "李四";
studentMap[1003] = "王五";
cout << "学号为 1002 的同学叫:" << studentMap[1002] << endl;
📌 输出:
学号为 1002 的同学叫:李四
🧠 六、map 的应用场景 🌐
场景 | 说明 |
---|---|
学生信息管理 | 学号作为 key,姓名/成绩作为 value |
字典查询系统 | 单词作为 key,释义作为 value |
缓存系统 | URL 作为 key,页面内容作为 value |
统计单词频率 | 单词作为 key,出现次数作为 value |
🎨 七、可视化图解 📊
初始状态:
{ }
添加 ("apple", "苹果"):
{ "apple" : "苹果" }
添加 ("dog", "狗"):
{ "apple" : "苹果", "dog" : "狗" }
添加 ("car", "汽车"):
{ "apple" : "苹果", "car" : "汽车", "dog" : "狗" }
📌 八、注意事项 ❗
注意点 | 说明 |
---|---|
key 不可重复 | 如果插入相同 key,会覆盖旧值 |
自动排序 | 默认按照 key 升序排列(可自定义比较函数) |
查找安全 | 使用 find() 或 count() 判断是否存在再访问,避免越界 |
🧩 九、进阶技巧 🔥
✅ 1. 自定义类型作为 Key
struct Student {
int id;
bool operator<(const Student& other) const {
return id < other.id;
}
};
map<Student, string> customMap;
customMap[{1001}] = "张三";
✅ 2. 初始化列表初始化(C++11 起)
map<string, int> scores = {
{"语文", 90},
{"数学", 95},
{"英语", 88}
};
🎁 十、小彩蛋:multimap 和 unordered_map 🎲
容器名 | 特点 |
---|---|
map |
按 key 排序,key 唯一 |
multimap |
支持重复 key |
unordered_map |
不排序,基于哈希表,查找更快(但不保证顺序) |
🏆 十一、加油鼓励语 💪
👋 小伙伴们,你们已经掌握了 C++ 中非常实用的
map
容器!它不仅逻辑清晰,而且功能强大,是解决很多实际问题的好帮手!
🎯 记住一句话:“程序 = 数据结构 + 算法”。
而 map
正是你通往算法高手之路的重要工具之一!
🚀 继续努力,坚持练习,你一定能在编程世界中大放异彩!我们在这里为你打call!👏👏👏
📝 十二、参考资料 & 推荐学习 🔍
资源名称 | 地址 |
---|---|
C++ Reference - map | https://cplusplus.com/reference/map/map/ |
LeetCode map 相关题目 | https://leetcode.cn/tag/map/ |
Bilibili C++ STL 教程 | https://www.bilibili.com/video/xxx |
📅 最后更新时间:2025年5月22日 22:17
🎉 祝你学得开心,编程顺利,早日成为大神!🌟
2 条评论
-
admin SU @ 2025-5-22 22:26:24
🧩 C++
map
与pair
联合教程 | 键值对的完美搭档!🌟
🎯 一、什么是 map 和 pair?
在 C++ 中,
map
是一个关联容器,用于存储 键值对(Key-Value Pair)。
而pair
是一个结构体模板,可以用来保存两个不同类型的值,非常适合表示“键值对”。你可以把它们想象成:
📦
map
就像一本字典,每个单词对应一个解释;
📎pair
就是字典中的每一行记录(单词 + 解释)。
🔍 二、知识点速览 📚
内容 描述 map
容器存储键值对,默认按 key 排序 pair
结构体表示一组键值对 <key, value>
头文件 <map>
和<utility>
使用方式 using namespace std;
常用操作 添加元素、遍历、查找、删除等
🧱 三、基础概念详解
✅ 1.
pair
简介#include <iostream> #include <utility> // pair 所在头文件 using namespace std; int main() { pair<string, int> p("小明", 90); // 创建一个 pair:姓名 + 分数 cout << "姓名:" << p.first << endl; // 输出:小明 cout << "分数:" << p.second << endl; // 输出:90 return 0; }
📌 特点:
- 只能保存两个元素
- 元素类型可以不同
- 访问方式:
.first
和.second
✅ 2.
map
简介#include <iostream> #include <map> using namespace std; int main() { map<string, int> scores; scores["语文"] = 85; scores["数学"] = 92; scores["英语"] = 88; cout << "数学成绩:" << scores["数学"] << endl; // 输出:92 return 0; }
📌 特点:
- 自动排序(默认升序)
- Key 不可重复
- 支持快速查找和插入
🧪 四、map 与 pair 的结合使用 💡
在
map
中,每一条记录都是一个pair
类型的对象!✅ 示例:遍历 map 中的 pair
#include <iostream> #include <map> using namespace std; int main() { map<string, int> scores = { {"语文", 85}, {"数学", 92}, {"英语", 88} }; for (auto it = scores.begin(); it != scores.end(); ++it) { // it 指向的是一个 pair<const K, V> cout << it->first << " -> " << it->second << endl; } return 0; }
📌 输出:
数学 -> 92 英语 -> 88 语文 -> 85
🔍 说明:
it->first
就是 key(科目名)it->second
就是 value(分数)
🎨 五、可视化图解 📊
map<string, int> scores: [ 数学 ] → 92 [ 英语 ] → 88 [ 语文 ] → 85
这其实是一个个的
pair<const string, int>
对象组成的有序结构!
🔧 六、常用操作一览表 ⚙️
方法 功能说明 map[key] = value
插入或修改键值对 map.insert(make_pair(key, value))
使用 pair 插入 map.find(key)
查找某个 key 是否存在 map.count(key)
判断 key 是否存在(返回 0 或 1) map.erase(key)
删除指定 key map.size()
返回键值对数量 map.empty()
判断是否为空
🧪 七、代码进阶示例 🚀
✅ 示例 1:使用
make_pair
插入元素scores.insert(make_pair("物理", 95));
✅ 示例 2:判断 key 是否存在
if (scores.count("化学")) { cout << "化学成绩已录入" << endl; } else { cout << "化学成绩未录入" << endl; }
✅ 示例 3:删除一个键值对
scores.erase("英语");
📌 八、注意事项 ❗
注意点 说明 key 不可重复 同一个 key 多次插入会覆盖旧值 自动排序 默认按照 key 升序排列 遍历顺序 不一定是插入顺序,而是排序后的顺序 迭代器访问 必须通过 .first
和.second
获取键值
🧠 九、应用场景举例 💡
场景 示例 学生成绩管理 map<int, string>
学号 → 姓名统计词频 map<string, int>
单词 → 出现次数缓存系统 map<string, string>
URL → 页面内容字典查询 map<string, string>
单词 → 释义
🎁 十、小彩蛋:unordered_map 和 multimap 🎲
容器 特点 map
按 key 排序,key 唯一 multimap
支持重复 key,依然排序 unordered_map
不排序,基于哈希表,查找更快(但不保证顺序)
🏆 十一、加油鼓励语 💪
👋 亲爱的同学,你已经掌握了 C++ 中非常实用的
map
和pair
,这是迈向编程高手的重要一步!🎯
map
是你解决实际问题的好帮手,
🧩pair
是你理解数据结构的钥匙,
🧠 把它们结合起来,你会发现很多算法题迎刃而解!🚀 继续努力,坚持练习,你一定能在编程世界中大放异彩!我们在这里为你打call!👏👏👏
📝 十二、参考资料 & 推荐学习 🔍
资源名称 地址 C++ Reference - map https://cplusplus.com/reference/map/ C++ Reference - pair https://cplusplus.com/reference/utility/pair/ LeetCode map 相关题目 https://leetcode.cn/tag/map/ Bilibili C++ STL 教程 https://www.bilibili.com/video/xxx
📅 最后更新时间:2025年5月22日 22:20
🎉 祝你学得开心,编程顺利,早日成为大神!🌟
-
2025-5-22 22:25:02@
🗺️ C++ map 完全教程:从入门到精通
🌟 欢迎进入映射的世界
在编程中,我们经常需要处理"键-值"对应的数据,比如"学号-姓名"、"单词-释义"这样的关系。这时候,C++的
map
容器就像一把万能钥匙,能帮我们快速找到需要的数据。今天就让我们一起探索这个强大的工具吧!🧩 什么是 map?
map
是C++标准库中的关联容器,它存储的是键值对(key-value pairs),特点是:- 键唯一:每个键只能出现一次
- 有序存储:默认按键的升序排列
- 快速查找:通过键可以快速找到对应的值
🌰 生活中的 map 比喻
map 就像一本字典:
- "单词"是键(key)
- "释义"是值(value)
- 通过单词可以快速查到释义,就像map通过键查值
┌───────────────┐ │ 键-值对 │ ├───────────────┤ │ "apple" : "苹果" │ ├───────────────┤ │ "book" : "书" │ ├───────────────┤ │ "cat" : "猫" │ └───────────────┘
📦 如何使用 map?
🔧 基本用法
首先,我们需要包含头文件并声明命名空间:
#include <iostream> #include <map> // map的头文件 using namespace std;
🚀 简单示例
下面是一个完整的示例,展示map的基本操作:
#include <iostream> #include <map> using namespace std; int main() { // 创建一个string到int的map,存储"单词-出现次数" map<string, int> wordCount; // 1. 插入元素 wordCount["apple"] = 5; // 方式1:通过键直接赋值 wordCount.insert({"banana", 3}); // 方式2:使用insert函数 wordCount.insert(pair<string, int>("cherry", 2)); // 方式3:使用pair // 2. 访问元素 cout << "apple出现次数: " << wordCount["apple"] << endl; // 输出: 5 // 3. 查找元素 if (wordCount.find("banana") != wordCount.end()) { cout << "banana存在,出现次数: " << wordCount["banana"] << endl; // 输出: 3 } // 4. 修改元素 wordCount["apple"] = 6; // 修改apple的出现次数 cout << "修改后apple出现次数: " << wordCount["apple"] << endl; // 输出: 6 // 5. 删除元素 wordCount.erase("cherry"); cout << "删除cherry后,map大小: " << wordCount.size() << endl; // 输出: 2 // 6. 遍历map cout << "遍历map中的所有元素:" << endl; for (const auto& pair : wordCount) { cout << pair.first << ": " << pair.second << endl; } // 7. 检查map是否为空 if (wordCount.empty()) { cout << "map为空" << endl; } else { cout << "map不为空" << endl; } return 0; }
🛠️ map 的常用操作
📋 核心操作列表
操作 描述 时间复杂度 map[key] = value
插入或修改键值对 O(log n) map.insert(pair)
插入键值对 map.find(key)
查找键,返回迭代器 map.erase(key)
删除指定键的元素 map.size()
获取元素个数 O(1) map.empty()
检查是否为空 map.clear()
清空map O(n) 🔍 深入理解迭代器
map的迭代器是双向迭代器,可以顺序遍历元素:
map<string, int>::iterator it; for (it = wordCount.begin(); it != wordCount.end(); ++it) { cout << it->first << ": " << it->second << endl; }
C++11引入了
auto
关键字,让代码更简洁:for (auto it = wordCount.begin(); it != wordCount.end(); ++it) { ... }
C++11还支持范围for循环,更加简洁:
for (const auto& pair : wordCount) { cout << pair.first << ": " << pair.second << endl; }
🌳 map 的底层实现
map的底层是红黑树(Red-Black Tree),这是一种自平衡二叉搜索树。
🌰 红黑树的特点:
- 每个节点不是红色就是黑色
- 根节点和叶节点(NULL)是黑色
- 红色节点的子节点必须是黑色
- 从任一节点到其所有叶节点的路径都包含相同数量的黑色节点
这种结构保证了map的操作时间复杂度稳定在O(log n),比普通二叉搜索树更高效。
📝 实战:用 map 统计单词频率
下面是一个实用案例,使用map统计文本中单词的出现频率:
#include <iostream> #include <map> #include <string> #include <cctype> using namespace std; // 清洗单词:转为小写并去除标点 string cleanWord(const string& word) { string result; for (char c : word) { if (isalpha(c)) { // 只保留字母 result += tolower(c); // 转为小写 } } return result; } int main() { map<string, int> wordFrequency; string word; cout << "请输入文本(输入end结束):" << endl; while (cin >> word) { if (word == "end") break; string cleanWord = cleanWord(word); if (!cleanWord.empty()) { wordFrequency[cleanWord]++; // 统计单词频率 } } cout << "\n单词频率统计结果:" << endl; for (const auto& pair : wordFrequency) { cout << pair.first << ": " << pair.second << "次" << endl; } return 0; }
输入示例:
Hello world hello hello World end
输出结果:
单词频率统计结果: hello: 3次 world: 2次
⚙️ map vs unordered_map
C++还有一个
unordered_map
,它和map
有什么区别呢?📊 对比表格
特性 map unordered_map 底层实现 红黑树 哈希表(Hash Table) 有序性 按键升序排列 无序 查找时间 O(log n) 平均O(1),最坏O(n) 插入时间 空间效率 较高 较低(需要哈希表开销) 何时选择?
- 需要有序存储时,选择
map
- 追求最快查找速度时,选择
unordered_map
- 数据量很大且分布均匀时,
unordered_map
更优
💡 实用技巧
1. 初始化map的多种方式
// 方式1:逐个插入 map<int, string> student; student[1001] = "张三"; student[1002] = "李四"; // 方式2:使用initializer_list (C++11+) map<int, string> student = { {1001, "张三"}, {1002, "李四"} }; // 方式3:从另一个map复制 map<int, string> student2(student);
2. 处理不存在的键
当访问一个不存在的键时,
map[key]
会自动插入该键并赋值为默认值:map<string, int> counter; counter["apple"]++; // 即使apple不存在,也会自动初始化为0再++
如果不想自动插入,可以用
find()
方法先检查:if (counter.find("banana") != counter.end()) { counter["banana"]++; }
3. 自定义比较函数
默认情况下,map按键的升序排列。如果需要自定义排序规则,可以传入比较函数:
// 按键的降序排列 map<int, string, greater<int>> descMap; // 自定义结构体作为键,并自定义比较 struct Person { string name; int age; // 自定义比较运算符 bool operator<(const Person& other) const { if (age != other.age) return age < other.age; return name < other.name; } }; map<Person, string> personMap;
🚀 挑战:用 map 实现简单通讯录
下面是一个进阶案例,实现一个具有添加、查询、删除功能的通讯录:
#include <iostream> #include <map> #include <string> using namespace std; int main() { map<string, string> addressBook; int choice; string name, phone; while (true) { cout << "\n=== 简单通讯录 ===" << endl; cout << "1. 添加联系人" << endl; cout << "2. 查询联系人" << endl; cout << "3. 删除联系人" << endl; cout << "4. 显示所有联系人" << endl; cout << "0. 退出" << endl; cout << "请选择操作: "; cin >> choice; if (choice == 0) break; switch (choice) { case 1: cout << "请输入姓名: "; cin >> name; cout << "请输入电话: "; cin >> phone; addressBook[name] = phone; cout << "联系人添加成功!" << endl; break; case 2: cout << "请输入要查询的姓名: "; cin >> name; if (addressBook.find(name) != addressBook.end()) { cout << name << "的电话是: " << addressBook[name] << endl; } else { cout << "未找到该联系人!" << endl; } break; case 3: cout << "请输入要删除的姓名: "; cin >> name; if (addressBook.erase(name)) { cout << "联系人删除成功!" << endl; } else { cout << "未找到该联系人!" << endl; } break; case 4: if (addressBook.empty()) { cout << "通讯录为空!" << endl; } else { cout << "所有联系人:" << endl; for (const auto& pair : addressBook) { cout << pair.first << ": " << pair.second << endl; } } break; default: cout << "无效选择,请重试!" << endl; } } cout << "感谢使用通讯录,再见!" << endl; return 0; }
🌟 总结与鼓励
恭喜你完成了map的学习!现在你已经掌握了:
- map的基本概念和特点(键值对、有序、唯一)
- map的常用操作(插入、查询、修改、删除)
- map的底层实现(红黑树)
- map与unordered_map的区别
- 多个实用案例和技巧
编程就像拼图,每个知识点都是重要的一块。map作为C++中非常实用的容器,在算法竞赛、实际开发中都有广泛应用。不要害怕遇到困难,每一次尝试都是进步的阶梯!
📚 拓展学习
- 学习STL中的其他关联容器:set、multiset、multimap
- 深入理解红黑树的原理和实现
- 探索unordered_map的哈希函数定制
- 用map解决更多实际问题,比如统计字符频率、实现缓存系统
记住,编程的乐趣在于不断探索和实践。继续加油,你一定能成为编程高手! 🚀
- 1