关联容器类型
map
std::map
是一个基于红黑树的有序关联容器,它存储的是键值对。每个键都是唯一的,并且容器会根据键来排序元素。在 std::map
中,查找、插入和删除操作的时间复杂度通常是 O(log n),其中 n 是容器中元素的数量。由于它是基于红黑树实现的,所以元素始终是有序的。
set
std::set
也是一个基于红黑树的有序关联容器,但它只存储唯一的键,没有与键相关联的值。和 std::map
一样,std::set
中的元素按照键排序,且查找、插入和删除操作的时间复杂度也是 O(log n)。
unordered_map
std::unordered_map
是一个基于哈希表的无序关联容器,它存储键值对,但不按任何特定顺序排序元素。在哈希表中,元素的位置由其键的哈希值决定。理想情况下,std::unordered_map
中的查找、插入和删除操作的平均时间复杂度是 O(1)。但在最坏的情况下(例如当哈希冲突非常频繁时),这些操作的时间复杂度可能退化到 O(n)。
unordered_set
std::unordered_set
是一个基于哈希表的无序关联容器,它只存储唯一的键。与 std::unordered_map
类似,std::unordered_set
不保持元素的顺序,查找、插入和删除操作的平均时间复杂度也是 O(1),但在最坏情况下可能退化到 O(n)。
补充:pair类型
std::pair
在关联容器(如 std::map
和 std::multimap
)中扮演着重要角色。在这些容器中,元素是以键值对的形式存储的,其中键和值分别对应 std::pair
的 first
和 second
成员。例如,std::map
容器的元素类型就是 std::pair<const Key, T>
,其中 Key
是键的类型,T
是值的类型。
当你向 std::map
插入元素时,通常会提供一个 std::pair
对象,或者使用 std::make_pair
:
std::map<int, std::string> myMap;
myMap.insert(std::make_pair(1, "One"));
myMap[2] = "Two";
当你从 std::map
获取元素时,也会得到一个 std::pair
类型的对象:
for (const auto& kv : myMap) {
std::cout << "Key: " << kv.first << ", Value: " << kv.second << std::endl;
}
关联容器操作
insert 方法
insert
方法用于向关联容器中添加新元素。它有几种重载形式:
- 单个元素插入:可以插入一个由
std::pair
构成的键值对。如果键已经存在,插入将不会进行,因为map
和set
的键是唯一的。
std::map<int, std::string> m;
m.insert(std::make_pair(10, "ten"));
- 初始化列表插入:可以插入一个初始化列表中的多个元素。
m.insert({{1, "one"}, {2, "two"}});
- 范围插入:可以插入另一个相同类型容器的元素范围。
std::map<int, std::string> m2;
m2.insert(m.begin(), m.end()); // 将 m 中的所有元素插入 m2
erase 方法
erase
方法用于从关联容器中删除元素,也有几种重载形式:
- 通过迭代器删除:删除指定迭代器位置的元素。
auto it = m.find(10);
if (it != m.end()) {
m.erase(it);
}
- 通过键删除:删除具有特定键的元素(对于
multimap
和multiset
,会删除所有具有该键的元素)。
m.erase(10); // 删除键为 10 的元素
- 通过迭代器范围删除:删除指定迭代器范围内的所有元素。
m.erase(m.begin(), m.find(10)); // 删除到键为 10 的元素之前的所有元素
find 方法
find
方法根据键来查找元素,如果找到,则返回指向该元素的迭代器;否则,返回指向容器 end
的迭代器。
auto it = m.find(10);
if (it != m.end()) {
// 找到了键为 10 的元素
}
count 方法
count
方法返回具有特定键的元素数量。对于 set
和 map
,结果要么是 0(未找到),要么是 1(找到)。对于 multiset
和 multimap
,可以是任何非负整数,表示键出现的次数。
size_t numItems = m.count(10); // 返回键为 10 的元素数量
lower_bound 和 upper_bound 方法
这两个方法用于在有序关联容器(如 map
和 set
)中查找特定键的边界。
lower_bound
返回指向第一个不小于给定键的元素的迭代器。upper_bound
返回指向第一个大于给定键的元素的迭代器。
auto lb = m.lower_bound(10);
auto ub = m.upper_bound(10);
equal_range 方法
equal_range
返回一个由两个迭代器组成的 pair
,表示特定键的范围。第一个迭代器等同于 lower_bound
的结果,第二个迭代器等同于 upper_bound
的结果。
auto range = m.equal_range(10);
// range.first -> lower_bound
// range.second -> upper_bound
下标操作符 []
对于 std::map
和 std::unordered_map
,可以使用下标操作符 []
来访问元素。如果键不存在,将会插入一个具有该键的新元素,并返回其值的引用。
std::map<int, std::string> m;
m[10] = "ten"; // 如果键 10 不存在,将创建新元素
std::string value = m[10]; // 访问键为 10 的元素的值
下标操作符不能用于 std::set
和 std::multiset
,因为这些容器不存储键值对,只存储单一的键。