前言
在 C++ 数据结构的学习中,除了序列式容器(如 vector、list),关联式容器同样占据核心地位。set 和 map 是其中最常用的两种,它们底层通常基于红黑树实现,能够自动维护元素的有序性。
一、序列式容器与关联式容器
序列式容器:如 string、vector、list 等,逻辑结构为线性序列,元素按存储位置顺序保存和访问。
关联式容器:逻辑结构通常为非线性,元素按关键字保存和访问。主要分为树形结构(map/set)和哈希结构(unordered_map/unordered_set)。本章重点讲解基于红黑树的 map 和 set。
简单理解:set 是 key 搜索场景的结构;map 是 key/value 搜索场景的结构。
二、键值对
键值对(Key-Value Pair)表示具有一一对应关系的结构,包含 key 和 value 两个成员变量。例如字典中单词与其含义的对应关系。
三、树形结构的关联式容器
STL 实现了两种不同结构的关联式容器:树型结构与哈希结构。树型结构主要有四种:map、set、multimap、multiset。
它们的共同点是使用平衡搜索树(即红黑树)作为底层结构,采用中序遍历,容器中的元素是一个有序的序列。
四、Set
1. Set 简介
set 是按照一定次序存储元素的容器。在 set 中,元素的 value 就是 key,且每个 value 必须是唯一的。插入时只需插入 value 即可,无需构造键值对。
内部元素总是按照比较对象指示的特定严格弱排序准则进行排序。查找某个元素的时间复杂度为 O(log n)。set 中的元素不允许修改,以保证数据排序和搜索树结构。
注意:虽然 set 只放 value,但在底层实际存放的是由 <value, value> 构成的键值对。
2. Set 的构造和迭代器
set 支持正向和反向迭代遍历,默认按升序顺序(因为底层是二叉搜索树,迭代器遍历走中序)。支持迭代器就意味着支持范围 for 循环。
// 无参默认构造
std::set<int> s;
// 迭代器区间构造
std::set<int> s2(it1, it2);
// 拷贝构造
std::set<int> s3(s);
// 初始化列表构造
std::set<int> s4 = {1, 2, 3};
// 迭代器类型
std::set<int>::iterator it = s.begin();
std::set<int>::reverse_iterator rit = s.rbegin();
3. Set 的增删查
主要关注以下接口:
insert: 单个数据插入(若存在则失败)、列表插入、迭代器区间插入。find: 查找 val,返回所在迭代器,未找到返回 end()。


