目录
00.引言
set 和 map 的区别
set 和 map 都是C++标准模板库(STL)中的容器,它们的区别如下:
-
set
是一个集合容器,存储的是唯一的元素,元素本身就是它的值,且元素按照某种顺序进行存储。set
不允许存储重复元素,常用于去重场景。 -
map
是一种键值对容器,存储的是成对的数据(key-value pairs),其中键(key)是唯一的,值(value)可以重复。map
主要用于通过键快速访问对应的值。
键值对的概念
键值对(Key-Value Pair)是指一种数据结构,其中每个数据项都由两个部分组成:键(key)和值(value)。键是唯一的,通过键可以快速找到对应的值。键值对的应用广泛,特别是在映射、查找、统计和数据关联等场景中。
键值对的特性
键是唯一的:在键值对中,每个键都是唯一的,不能有重复的键。
值可以重复:虽然键是唯一的,但对应的值可以重复,即多个键可以映射到相同的值。
例如,在 map 容器中:
map<string, int> myMap;
myMap["apple"] = 10; // "apple" 是键,10 是值
myMap["banana"] = 20;
myMap["apple"] = 20; // 值可以被修改,也可以重复
01.map容器
map 是一种存储键值对的关联容器,底层通过红黑树实现,元素按照键进行排序,其提供了高效的插入、删除和查找操作。
主要特性
-
键值对存储:每个元素由一个键和一个值组成,键通过某种排序规则存储,且键是唯一的。
-
自动排序:
map
中的元素默认按照键的升序排序。可以使用自定义比较函数改变排序方式。 -
查找效率:
map
使用红黑树(平衡二叉搜索树)作为底层结构,查找、插入和删除操作的时间复杂度为 O(log n)。
常用操作
1.插入元素:通过下标运算符 [] 或 insert 方法插入键值对:
map<string, int> myMap;
myMap["apple"] = 10; // 插入键为 "apple",值为 10 的键值对
myMap.insert(make_pair("banana", 20)); // 使用 insert 插入键值对
要明白下标运算符 [] 是如何完成插入操作的,就要了解其底层逻辑,下图是官方的说明:
具体的说,如果 myMap[ k ] 此时元素k的键已存在,就会返回其对应的值的引用,既可以查看也可以修改;如果元素k的键不存在,则会插入一个元素k的新键,也会返回对应值的引用(默认为0)
2.查找元素:使用 find 方法查找键对应的值,返回指向键值对的迭代器,如果找不到对应的键,那么会返回一个指向 map 末尾的迭代器 map.end():
auto it = myMap.find("apple");
if (it != myMap.end()) {
cout << it->first << ": " << it->second << endl;
}
3.删除元素:使用 erase 方法删除指定键的元素:
myMap.erase("apple");
4.遍历元素:可以通过迭代器遍历 map 中的所有键值对:
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
主要用途
1.关联数组:将一个键映射到一个值,常用于模拟字典或关联数组。
2.统计频率:可以用来统计元素出现的次数,如统计单词的出现频率。
3.数据映射:适合用于需要快速查找键值对应关系的场景,比如用户 ID 与姓名的映射。
02.multimap容器
在 C++ 标准模板库(STL)中,map
和 multimap
存储的是键值对(key-value pairs),但它们之间有显著的区别:
键的唯一性:
map:键是唯一的,每个键只能对应一个值。如果插入一个已经存在的键,新值会替换旧值
multimap:允许键重复,即同一个键可以对应多个值。它适用于需要存储相同键的多个值的场景。
特性
multimap
适合用于存储一对多关系的数据。
键可重复:multimap
中的键不必唯一,同一个键可以对应多个值。
自动排序:multimap
和 map
一样,键默认是按升序自动排序的。
查找效率:和 map
一样,multimap
的查找、插入、删除操作的时间复杂度都是 O(log n)。
常用操作
1.插入操作:使用 insert 方法插入键值对,支持同一个键插入多个不同的值。
multimap<string, int> myMultimap;
myMultimap.insert(make_pair("apple", 10));
myMultimap.insert(make_pair("apple", 20)); // 允许相同键插入
注意:multimap
不能 使用 []
运算符进行插入或访问。
这是因为 multimap
允许键重复,而 []
运算符需要确保键是唯一的。[]
在 map
中的行为是根据键查找对应的值,如果键不存在就插入一个新的键值对并返回引用,这种行为与 multimap
的多键特点冲突。
2.查找元素:
a. 使用 find
查找第一个匹配的键。
b. 使用 equal_range
方法查找某个键对应的所有值,返回一个范围(pair of iterators)。
auto range = myMultimap.equal_range("apple");
for (auto it = range.first; it != range.second; ++it) {
cout << it->first << ": " << it->second << endl;
}
3.删除元素:使用 erase 方法删除某个键的所有值或单个键值对
删除所有键值对:
myMultimap.erase("apple"); // 删除所有 "apple" 的键值对
删除单个键值对:通过迭代器遍历删除
auto it = myMultimap.find("apple");
for (; it != myMultimap.end(); ++it) {
if (it->second == 20) {
myMultimap.erase(it); // 通过迭代器删除该键值对
break;
}
}
或者:通过范围迭代删除特定键值对
// 获取 "apple" 键的范围
auto range = myMultimap.equal_range("apple");
// 在范围内查找并删除值为 20 的键值对
for (auto it = range.first; it != range.second; ++it) {
if (it->second == 20) {
myMultimap.erase(it); // 通过迭代器删除
break;
}
}
4.遍历元素:可以像遍历 map
一样遍历 multimap
中的所有键值对。
for (const auto& pair : myMultimap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
用途
1.一对多映射:multimap
适合用于一对多的映射关系,比如在存储课程和学生名单时,一个课程可以有多个学生。
2.多重计数:当需要统计多个相同键对应不同值的情况时,multimap
是一种便捷的工具。
以上就是map和multimap的相关知识总结,欢迎在评论区留言,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉