前言
在C++中,map和set是两种非常常用的关联容器(Associative Containers),它们的底层实现通常是红黑树,这使得它们的查找、插入、删除操作都可以在对数时间内完成。在这篇文章中,我们将探讨它们的基本概念、常用操作以及使用场景。
set:唯一且有序的集合
什么是 set?
set是一个集合类,它存储“唯一的元素”,并且按照某种顺序自动排序(默认是升序)。如果你想存储一组不会重复的元素,并且不需要显式指定顺序,set是一个非常好的选择。
基本操作
插入元素
使用insert方法可以插入元素,并且会自动按顺序排列。
#include <iostream>
#include <set>
int main() {
std::set<int> s;
s.insert(3);
s.insert(1);
s.insert(4);
for (int x : s) {
std::cout << x << " "; // 输出:1 3 4
}
}
在上面的代码中,set会自动为你将元素按顺序排列。
查找元素
set提供了高效的查找方法,使用find可以快速定位某个元素。
if (s.find(1) != s.end()) {
std::cout << "1 存在于集合中";
}
删除元素
erase方法可以用来删除元素:
s.erase(3); // 删除元素3
set的典型应用场景
去重:当你需要存储一组不重复的元素时,set是很好的选择,比如存储唯一的用户ID。
集合操作:set还支持集合的交集、并集等操作,适合处理类似数学中的集合问题。
map:键值对的存储
什么是map?
map是一种存储键值对(key-value pair)的容器。每个元素都有一个唯一的“键”(key)和对应的“值”(value)。键是唯一的,值可以重复。`map` 内部自动按键的顺序(默认是升序)进行排列,方便高效查找。
基本操作
插入元素
通过使用operator[ ]或者insert来插入键值对:
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> age;
age["Alice"] = 25;
age["Bob"] = 30;
for (auto& pair : age) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
}
输出结果为:
Alice:25
Bob:30
查找元素
使用find可以根据键查找对应的值:
auto it = age.find("Alice");
if (it != age.end()) {
std::cout << "Alice 的年龄是 " << it->second;
}
删除元素
map也支持使用erase来删除某个键值对:
age.erase("Bob"); // 删除键为"Bob"的元素
map的典型应用场景
字典结构:当你需要通过唯一的键来快速访问对应的值时,map 是非常好的选择。比如,可以用map来存储学生的成绩单,以名字作为键,成绩作为值。
计数统计:常见的应用场景是使用map来统计某些数据出现的频率,比如统计一篇文章中每个单词的出现次数。
set和map的底层实现:树形结构关联式容器
set和 map是树形结构的关联式容器,它们的底层通常由红黑树(Red-Black Tree)实现。红黑树是一种自平衡的二叉搜索树(Binary Search Tree, BST),它具备以下性质:
有序性:在红黑树中,节点会按照键的顺序排列,这就是为什么 set和map内部的数据是自动排序的。
平衡性:红黑树会在插入和删除操作时自动调整,保证树的高度维持在O(log n) 的范围内。这使得我们可以在O(log n)时间内完成查找、插入和删除操作。
为什么使用树形结构?
红黑树作为底层数据结构的关键优势在于它的平衡性。普通的二叉搜索树在极端情况下可能会退化成一个链表,导致查找、插入等操作退化为线性时间。而红黑树通过对节点颜色(红或黑)的约束条件,保证了树的平衡,防止出现这种退化现象。
因此,set和map能在不牺牲性能的前提下,保持元素有序排列,同时提供高效的查找、插入、删除操作。
unordered_map和unordered_set
在某些场景下,如果不关心元素的顺序,而更注重查找的速度,C++还提供了哈希表的实现,即unordered_map和unordered_set。它们的查找、插入、删除操作的时间复杂度为O((1),但由于哈希冲突等原因,性能可能会出现波动。
使用建议:
如果你需要有序的键值对或集合,请使用map和set。
如果你不关心顺序而且追求更快的查找速度,请使用unordered_map和unordered_set。
总结
set是一个存储唯一元素的有序集合,适合用于去重和集合操作。
map是一个存储键值对的有序容器,适合快速查找和存储键值关系。
树形结构关联式容器:set和map底层通常由红黑树实现,具有 O(log n) 的操作效率。红黑树通过自平衡机制保证了数据的有序性和操作的高效性。
如果对顺序没有要求,可以考虑使用哈希表(unordered_map和unordered_set)在查找、插入等操作上具备更好的平均性能。
希望以上的文章对你有所帮助,感谢各位的观看!求点赞关注。