C++ STL 容器 set 常见用法总结
set 是 C++ STL 中的关联容器,特点是:
-
自动有序(默认从小到大)
-
元素唯一,不允许重复
-
底层通常是红黑树
-
插入、删除、查找的时间复杂度通常是 O(log n)
set 常用于:
-
去重
-
自动排序
-
快速查找某个数是否存在
-
维护动态有序序列
-
查找前驱 / 后继
1. 头文件与定义
基本定义
定义一个存放 int 的集合。
2. set 的基本特点
例如:
结果中只会保留:
说明:
-
自动升序排列
-
重复元素
3不会被插入第二次
3. 常用操作
3.1 insert():插入元素
结果只有:
因为 set 不允许重复元素。
3.2 erase():删除元素
按值删除
删除值为 10 的元素。
按迭代器删除
3.3 find():查找元素
3.4 count():统计某个元素出现次数
对于 set:
-
存在则返回
1 -
不存在则返回
0
因为 set 不会有重复元素。
3.5 size():元素个数
3.6 empty():判断是否为空
3.7 clear():清空集合
4. 遍历 set
因为 set 是有序的,所以遍历结果默认从小到大。
方式 1:范围 for
方式 2:迭代器
C++11 可简写为:
5. begin() 和 end()
-
begin():指向第一个元素 -
end():指向最后一个元素的下一个位置,不能直接解引用
例如:
6. 取最大值和最小值
最小值
最大值
或者:
注意:
- 前提是
set非空
7. 自动去重
这是 set 最经典的用途之一。
vector<int> a = {1, 2, 2, 3, 3, 3, 4};
set<int> s(a.begin(), a.end());
for (int x : s) cout << x << " ";
输出:
8. 判断某元素是否存在
也可以写:
比赛里这两种都常见。
9. 前驱和后继
这是 set 很重要的竞赛用法。
9.1 lower_bound(x)
返回第一个大于等于 x 的位置
9.2 upper_bound(x)
返回第一个大于 x 的位置
9.3 查找前驱
前驱:小于 x 的最大元素。
9.4 查找后继
后继:大于等于 x 的最小元素(常用 lower_bound)
10. 降序 set
默认是升序,如果想降序排列:
示例:
输出:
11. 删除区间元素
表示删除区间 [3, 7] 内的元素。
注意这里实际删除的是迭代器区间 [l, r)。
12. set<pair<int,int>> 的用法
比赛中也很常见。
pair 会按字典序排序:
-
先比较
first -
再比较
second
遍历结果:
13. 常见应用场景
13.1 去重 + 排序
13.2 动态查重
13.3 维护有序集合
例如随时需要:
-
插入元素
-
删除元素
-
查询最小值 / 最大值
-
查询某个值是否存在
这时 set 比 vector 更方便。
13.4 查找最接近某个值的元素
利用 lower_bound():
然后比较:
-
it -
prev(it)
即可找到最接近 x 的值。
14. 常见注意事项
14.1 set 中元素不能通过迭代器直接修改
错误写法:
原因:
- 修改元素会破坏内部有序性
如果要改,通常做法是:
-
先删
-
再插
14.2 find() 返回的是迭代器
不是返回下标。
14.3 end() 不能解引用
错误写法:
正确取最大值要写:
14.4 set 不支持下标访问
错误理解:
不存在这种写法。
因为 set 不是顺序容器。
14.5 插入重复元素不会报错,但不会成功插入
最后仍然只有一个 5。
15. 蓝桥杯常见模板
15.1 判重模板
15.2 去重排序模板
15.3 查找前驱后继模板
auto it = s.lower_bound(x);
// 后继
if (it != s.end()) cout << *it << endl;
// 前驱
if (it != s.begin()) {
--it;
cout << *it << endl;
}
16. 一份完整示例代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(3);
s.insert(1);
s.insert(5);
s.insert(3);
for (int x : s) cout << x << " ";
cout << endl; // 1 3 5
if (s.count(3)) cout << "3 存在" << endl;
s.erase(3);
if (s.find(3) == s.end()) cout << "3 已被删除" << endl;
cout << "最小值: " << *s.begin() << endl;
cout << "最大值: " << *prev(s.end()) << endl;
return 0;
}
17. 必背内容
定义
常用操作
s.insert(x); // 插入
s.erase(x); // 删除
s.find(x); // 查找
s.count(x); // 是否存在
s.lower_bound(x); // 第一个 >= x
s.upper_bound(x); // 第一个 > x
s.empty(); // 判空
s.size(); // 元素个数
遍历
18. 总结
set 的核心特点:
-
自动排序
-
元素唯一
-
查找 / 插入 / 删除效率高
-
非常适合动态维护有序不重复集合
蓝桥杯中最常见的几个方向:
-
去重
-
判重
-
有序维护
-
前驱后继
-
查找某数是否存在