深入理解 C++ 中的 map 和 set

前言

在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)在查找、插入等操作上具备更好的平均性能。

希望以上的文章对你有所帮助,感谢各位的观看!求点赞关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maker-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值