C++ 中 std::set 的用法

C++ 中 std::set 的用法

std::set 是 C++ STL 中的关联容器,基于红黑树实现,具有以下特点:

  • 元素唯一(自动去重)。
  • 元素自动有序(默认从小到大排序)。
  • 支持快速插入、删除、查找(时间复杂度 O(log N))。
  • 常用于需要维护有序唯一元素的场景。

头文件:#include <set>

基本声明:

cpp 复制代码
#include <set>
#include <iostream>
using namespace std;

set<int> s;  // 默认从小到大排序
set<int, greater<int>> s_desc;  // 从大到小排序(greater 是比较器)
常见操作
  • 插入s.insert(x);(如果已存在则不插入)

  • 删除s.erase(x);(删除值为 x 的元素)或 s.erase(it);(删除迭代器指向的元素)

  • 查找s.find(x);(返回迭代器,若不存在返回 s.end()

  • 计数s.count(x);(返回 0 或 1,因为唯一)

  • 大小s.size();

  • 清空s.clear();

  • 下界/上界

    • s.lower_bound(x);:返回 >= x 的第一个元素的迭代器
    • s.upper_bound(x);:返回 > x 的第一个元素的迭代器
  • 遍历

    cpp 复制代码
    for(auto it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    // 或 C++11 范围 for
    for(int x : s) {
        cout << x << " ";
    }
几个常见例子
  1. 去重并排序(经典应用:明明的随机数)

    cpp 复制代码
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n; cin >> n;
        set<int> s;
        for(int i = 0; i < n; i++) {
            int x; cin >> x;
            s.insert(x);  // 自动去重并排序
        }
        for(int x : s) cout << x << endl;
        return 0;
    }
  2. 维护动态有序集合,求前后继(如营业额统计,求每个数与最近数的差)

    cpp 复制代码
    set<int> s;
    s.insert(first_value);  // 插入第一个
    long long ans = 0;
    for(each new value x) {
        auto it = s.insert(x).first;  // 插入并获取迭代器
        if(it != s.begin()) {
            auto prev = prev(it);  // C++11 前驱
            ans += *it - *prev;
        }
        if(next(it) != s.end()) {
            ans += *next(it) - *it;
        }
        // ... 更新最小等
    }
  3. 检查是否存在 + 快速查找

    cpp 复制代码
    set<string> forbidden;
    forbidden.insert("badword1");
    forbidden.insert("badword2");
    string word; cin >> word;
    if(forbidden.count(word)) {
        cout << "禁止词!" << endl;
    }
  4. 木材仓库问题(插入/查询/删除相同长度的木材)

    cpp 复制代码
    multiset<int> ms;  // 如果允许重复,用 multiset
    // 或用 set + map 记录次数

洛谷和力扣(LeetCode)上的经典题目推荐

这些题目都很适合练习 set 的插入、查找、下界等操作。

洛谷(Luogu)经典题目:
  • P5250 【深基17.例5】木材仓库 :经典 set/multiset 应用,维护木材长度,查询是否有相同长度。
    链接:https://www.luogu.com.cn/problem/P5250
  • P2234 [HNOI2002]营业额统计 :用 set 维护已出现数字,lower_bound/upper_bound 求最近差值。
    链接:https://www.luogu.com.cn/problem/P2234
  • P3370 【模板】字符串哈希 :用 set 存储哈希值去重统计不同字符串数(简单去重)。
    链接:https://www.luogu.com.cn/problem/P3370
  • NOIP2006 明明的随机数(或类似去重排序题):直接 set 插入遍历输出。
  • P5266 【深基17.例6】学籍管理:set 维护学生信息,查询是否存在。

洛谷有专门的"【数据结构1-3】集合"题单,推荐直接刷:https://www.luogu.com.cn/training/158850#problems(包含更多 set 练习题)。

力扣(LeetCode)经典题目:
相关推荐
liulilittle13 小时前
CLANG 交叉编译
linux·服务器·开发语言·前端·c++
多米Domi01113 小时前
0x3f 第21天 三更java进阶1-35 hot100普通数组
java·python·算法·leetcode·动态规划
步步为营DotNet13 小时前
深深度探索.NET 中HttpClient的复用策略:提升性能与稳定性的关键度解析.NET 中IServiceCollection:构建可扩展服务体系的关键
java·网络·.net
牛马11114 小时前
WidgetsFlutterBinding.ensureInitialized()在 Flutter Web 端启动流程的影响
java·前端·flutter
宠友信息14 小时前
面向多端部署的社区平台技术方案:uniapp 与java微服务架构的工程化实践
java·微服务·微信·架构·uni-app·springboot
YanDDDeat14 小时前
Prometheus + Grafana 搭建应用监控体系
java·后端·eureka·grafana·prometheus
kylezhao201914 小时前
C#读取字节数组某个位的值
开发语言·c#
诗酒当趁年华14 小时前
Token刷新策略
java