C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ STL  set 和 map

C++ STL 中的 set 和 map从入门到实战指南

作者:破忒头456

本文系统讲解C++ STL中关联式容器set和map的核心特性与使用方法,涵盖底层红黑树实现,本文结合实例代码给大家介绍C++ STL中的 set 和map完全指南从入门到实战,感兴趣的朋友一起看看吧

一、 序列式容器 vs 关联式容器

    我们之前学过 string、vector、list、deque 等,它们统称为序列式容器,因为元素在逻辑上是线性排列的,位置之间没有强关联,交换两个元素不影响“序列”性质。

    而关联式容器(如 set、map、unordered_set 等)逻辑上通常是非线性的(树或哈希),元素之间通过关键字(key)来建立关联。交换两个元素可能会破坏结构,因为它们的位置是由关键字决定的。

(1)set系列:纯 key 搜索场景,比如判断一个值在不在集合中。

(2)map系列:key/value 搜索场景,比如字典(单词→释义)。

    本章讲的 map/set 底层是红黑树(平衡二叉搜索树),因此增删查效率为 O(log N),且迭代器遍历是中序,得到的是有序序列。

二、 set 系列详解

2.1 set 的声明与特点

template < class T, 
           class Compare = less<T>, 
           class Alloc = allocator<T> > 
class set;

2.2 构造与迭代器

set<int> s1;                          // 空
set<int> s2 = {5,1,5,2,6};            // initializer_list,自动去重
set<int> s3(s2.begin(), s2.end());    // 区间构造
set<int> s4(s3);                      // 拷贝构造

迭代器:

2.3 增删查核心接口

操作接口说明
插入insert(val)返回 pair<iterator,bool>,bool 表示是否成功(已存在则失败)
插入列表insert({...})批量插入,已存在忽略
查找find(key)返回迭代器,找不到返回 end(),O(log N)
计数count(key)返回 key 的个数(set 中只能是 0 或 1)
删除erase(key)删除等于 key 的元素,返回删除个数
删除erase(pos)删除迭代器位置
区间删除erase(first,last)删除 [first, last)
下界lower_bound(key)返回第一个 >= key 的迭代器
上界upper_bound(key)返回第一个 > key 的迭代器

2.4 综合示例:set 的基本操作

2.5 multiset —— 允许重复 key

multiset与set的唯一区别是不去重,其他接口基本一致,但有一些差异:

(1)insert总是成功。

(2)find(key)返回中序第一个等于 key 的迭代器。

(3)count(key)返回实际个数(可能 >1)。

(4)erase(key)会删除所有等于 key 的元素。

示例:

三、map 系列详解

3.1 pair 类型——key/value 的载体

map底层节点存储的是 pair<const key,T>,定义如下:

template <class T1, class T2>
struct pair {
    T1 first;   // key
    T2 second;  // value
    // 构造函数...
};

我们可以用make_pair或{}来创建 pair。

3.2 map 的声明与特点

template < class Key, 
           class T, 
           class Compare = less<Key>, 
           class Alloc = allocator<pair<const Key,T>> > 
class map;

3.3 构造与迭代器

与 set 类似,支持 initializer_list、区间、拷贝等。

map<string, string> dict = {
    {"left", "左边"},
    {"right", "右边"},
    {"insert", "插入"},
    {"sort", "排序"}
};

迭代器访问:

auto it = dict.begin();
while (it != dict.end()) {
    cout << it->first << ": " << it->second << endl;  // it->first 即 key
    ++it;
}

范围 for:

for (const auto& kv : dict) {
    cout << kv.first << ": " << kv.second << endl;
}

3.4 增删查接口

操作接口说明
插入insert({key, value})返回 pair<iterator,bool>,key 存在则失败
查找find(key)返回迭代器,可修改 value
计数count(key)返回 0 或 1(multimap 可>1)
删除erase(key)删除所有 key,返回删除个数
删除erase(pos)删除迭代器位置
区间删除erase(first,last)删除 [first,last)
下界/上界lower_bound/upper_bound同 set

3.5 核心:operator[] —— 插入+查找+修改三合一

operator[]是 map 最强大的接口,其内部实现等价于:

mapped_type& operator[](const key_type& k) {
    // 插入 {k, mapped_type()},如果已存在则返回已有迭代器
    pair<iterator, bool> ret = insert({k, mapped_type()});
    // 返回 value 的引用
    return ret.first->second;
}

行为:

因此 [] 可以用于:

⚠️ 注意:使用 [] 查找时,若 key 不存在会插入默认 value,可能不是你想要的行为,通常用 find 来纯粹查找。

3.6 综合示例

3.7multimap —— 允许 key 冗余

multimap与map的区别就是 key 可重复,因此:

四、总结

容器去重key 可修改value 可修改是否支持 []应用场景
set是否(整体不可改)—否快速去重、存在性判断
multiset否否—否允许重复的有序集合
map是否是是字典、映射、统计
multimap否否是否一对多映射(如一个key对应多个value

核心要点:

到此这篇关于C++ STL 中的 set 和 map 完全指南:从入门到实战的文章就介绍到这了,更多相关C++ STL set 和 map 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文