std::set (C++)
std::set
- 1. 概述
- 定义
- 特点
- 2. 内部实现
- 3. 性能特征
- 4. 常用 API
- 5. 使用示例
- 6. 自定义比较器
- 7. 注意事项与优化
- 8. 使用建议
1. 概述
定义
template<class Key,class Compare = std::less<Key>,class Allocator = std::allocator<Key>
>
class std::set;
特点
-
有序:所有元素按严格弱序(由 Compare 决定)排列,不保证相同键的重复出现(键唯一)。
-
唯一键:插入时如果集合中已有相同元素,不会增加新的节点。
-
底层结构:通常基于红黑树(balanced binary search tree)实现。
2. 内部实现
-
红黑树
- 平衡二叉查找树,保证从根到任一叶子路径的“黑色节点数”相同,从而令树高度为 O(log n)。
-
节点结构
- 每个节点存储:
- 元素值 Key
- 左/右子指针和父指针
- 一个颜色标记(红或黑)
- 每个节点存储:
-
拷贝与移动
- 拷贝时会对整棵树进行深拷贝;移动构造则接管底层指针,无需逐节点复制。
3. 性能特征
| 操作 | 平均复杂度 | 最坏复杂度 | 备注 |
|---|---|---|---|
| insert | O(log n) | O(log n) | 包括查找插入位置与调整平衡 |
| erase | O(log n) | O(log n) | 按键删除时需旋转与重着色 |
| find | O(log n) | O(log n) | |
| clear | O(n) | O(n) | 释放所有节点 |
| 遍历 | O(n) | O(n) | 中序遍历即可 |
-
内存开销:
- 每个节点需存储三个指针(左右、父)和一个颜色字段,相比哈希表更紧凑但比 std::vector 等顺序容器要高。
-
迭代器失效规则:
- 插入和删除会使仅被删除的节点的迭代器失效,其他节点迭代器保持有效。
4. 常用 API
// 构造与析构
std::set<Key> s1; // 默认构造
std::set<Key> s2({k1, k2, k3}); // 初始化列表
std::set<Key, Compare> s3(comp); // 指定比较器// 大小与容量
bool empty() const noexcept;
size_t size() const noexcept;
size_t max_size() const noexcept;// 元素访问
iterator find(const Key& key);
size_t count(const Key& key) const; // 要么 0,要么 1// 插入
std::pair<iterator,bool> insert(const Key& key);
iterator insert(iterator hint, const Key& key);
template<class... Args>
std::pair<iterator,bool> emplace(Args&&... args);// 删除
size_t erase(const Key& key);
iterator erase(iterator pos);
iterator erase(iterator first, iterator last);// 遍历
iterator begin() noexcept;
iterator end() noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;// 有序查询
iterator lower_bound(const Key& key); // ≥ key 的第一个位置
iterator upper_bound(const Key& key); // > key 的第一个位置
std::pair<iterator,iterator> equal_range(const Key& key);// 比较器与分配器访问
Compare key_comp() const;
Compare value_comp() const; // 同 key_comp
Allocator get_allocator() const noexcept;// 交换
void swap(std::set& other) noexcept;
5. 使用示例
#include <set>
#include <iostream>int main() {std::set<int> s;// 插入s.insert(3);s.emplace(1);s.insert({5, 2, 4});// 查找if (s.find(2) != s.end()) {std::cout << "2 存在\n";}// 遍历(中序:1,2,3,4,5)for (int x : s) {std::cout << x << " ";}std::cout << "\n";// 有序查询auto it = s.lower_bound(3); // 指向 3std::cout << "lower_bound(3): " << *it << "\n";// 删除s.erase(3); // 删除值为 3 的节点// 范围删除s.erase(s.begin(), s.lower_bound(4)); // 删除所有 <4 的元素// 清空s.clear();
}
6. 自定义比较器
当需要自定义排序规则(如降序或复合键)时,可提供自定义比较器:
struct Desc {bool operator()(int a, int b) const {return a > b; // 降序}
};std::set<int, Desc> s_desc; // 插入后,将按从大到小顺序存储
对于复合类型:
struct Person {std::string name;int age;
};struct ByAgeName {bool operator()(Person const& a, Person const& b) const {if (a.age != b.age) return a.age < b.age;return a.name < b.name;}
};// 年龄升序,若年龄相同则按名字升序
std::set<Person, ByAgeName> roster;
7. 注意事项与优化
-
避免不必要的拷贝
- insert(const Key&) 会拷贝一次;若可移动,优先使用 insert(Key&&) 或 emplace()。
-
hint 参数
- insert(hint, key):若能提供一个接近正确位置的迭代器 hint,可将插入复杂度降到常数时间。
-
批量插入
- 对初始化列表或范围插入,建议先 reserve()(C++23 起支持)或构造时传入范围,以减少重平衡次数。
-
避免迭代器失效
- 删除或插入仅影响相关节点迭代器,其他迭代器保持有效。
8. 使用建议
-
适用场景
- 需要自动排序且元素唯一时,首选 std::set。
- 需要查询前驱/后继、区间操作(lower_bound、upper_bound、中序遍历)时非常方便。
-
不适用场景
- 需要允许重复键或多对一映射时,改用 std::multiset 或 std::map。
- 对性能有极致要求且不在意顺序时,可考虑 std::unordered_set(哈希实现,平均 O(1))。
相关文章:
std::set (C++)
std::set 1. 概述定义特点 2. 内部实现3. 性能特征4. 常用 API5. 使用示例6. 自定义比较器7. 注意事项与优化8. 使用建议 1. 概述 定义 template<class Key,class Compare std::less<Key>,class Allocator std::allocator<Key> > class std::set;特点 有…...
STM32 HAL 通用定时器延时函数
使用通用定时器TIM3,实现ms、us延时。 delay.c #include "delay.h" #include "stm32f1xx_hal.h"TIM_HandleTypeDef htim3;/*** brief 初始化定时器3用于延时* param 无* retval 无*/ void Delay_Init(void) {TIM_ClockConfigTypeDef sClock…...
RK3588S开发板将SPI1接口改成GPIO
参考官方教程:ROC-RK3588S-PC 一.基本知识: 1.GPIO引脚计算: ROC-RK3588S-PC 有 5 组 GPIO bank:GPIO0~GPIO4,每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分,常用以下公式计算引脚:GPIO…...
PLOS ONE:VR 游戏扫描揭示了 ADHD 儿童独特的大脑活动
在孩子的成长过程中,总有那么一些“与众不同”的孩子。他们似乎总是坐不住,课堂上小动作不断,注意力难以集中,作业总是拖拖拉拉……这些行为常常被家长和老师简单地归结为“淘气”“不听话”。然而,他们可能并不只是“…...
DemoGen:用于数据高效视觉运动策略学习的合成演示生成
25年2月来自清华、上海姚期智研究院和上海AI实验室的论文“DemoGen: Synthetic Demonstration Generation for Data-Efficient Visuomotor Policy Learning”。 视觉运动策略在机器人操控中展现出巨大潜力,但通常需要大量人工采集的数据才能有效执行。驱动高数据需…...
极狐GitLab 账号限制有哪些?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 账户和限制设置 (BASIC SELF) 默认项目限制 您可以配置新用户能在其个人命名空间中创建的默认最大项目数。此限制仅影响更改…...
@JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染
JsonView 单一 DTO:如何实现多场景 JSON 字段动态渲染 JsonView 单一 DTO:如何实现多场景 JSON 字段动态渲染1、JsonView 注解产生的背景2、为了满足不同场景下返回对应的属性的做法有哪些?2.1 最快速的实现则是针对不同场景新建不同的 DTO…...
JVM之经典垃圾回收器
一、垃圾回收算法 1. 标记-清除(Mark-Sweep) 步骤: 标记:遍历对象图,标记所有存活对象。清除:回收未被标记的垃圾对象。 特点:简单,但会产生内存碎片。 2. 标记-复制(…...
15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回
前言 这也是最近碰到的一个问题 直连 流式 http 服务, 发现 流式响应正常, 0.1 秒接收到一个响应 但是 经过 nginx 代理一层之后, 就发现了 类似于缓冲的效果, 1秒接收到 10个响应 最终 调试 发现是 nginx 的 proxy_buffering 配置引起的 然后 更新 proxy_buffering 为…...
人工智能学习框架完全指南(2025年更新版)
一、核心框架分类与适用场景 人工智能框架根据功能可分为深度学习框架、机器学习框架、强化学习框架和传统工具库,以下是主流工具及选型建议: 1. 深度学习框架 (1)PyTorch 核心优势:动态计算图、灵活性强,适合科研与快速原型开发,支持多模态任务(如NLP、CV) 。技术生…...
安卓手机万能遥控器APP推荐
软件介绍 安卓手机也能当“家电总控台”?这款小米旗下的万能遥控器APP,直接把遥控器做成“傻瓜式操作”——不用配对,不连蓝牙,点开就能操控电视、空调、机顶盒,甚至其他品牌的电器!雷总这波操作直接封神&…...
颚式破碎机的设计
一、引言 颚式破碎机作为矿山、建材等行业的重要破碎设备,其性能优劣直接影响物料破碎效率与质量。随着工业生产规模的扩大和对破碎效率要求的提高,设计一款高效、稳定、节能的颚式破碎机具有重要意义。 二、设计需求分析 处理能力:根据目…...
PH热榜 | 2025-04-18
1. Wiza Monitor 标语:跟踪工作变动,接收Slack和电子邮件的提醒。 介绍:Wiza Monitor是一款用于追踪职位变动的工具,可以实时跟踪客户和潜在客户的工作变动,还可以通过电子邮件和Slack发送提醒,让你的客户…...
Android平台 Hal AIDL 系列文章目录
目录 1. Android Hal AIDL 简介2. AIDL 语言简介3. Android 接口定义语言 (AIDL)4. 定义AIDL 接口5. AIDL 中如何传递 Parcelable 对象6. 如何使用AIDL 定义的远程接口进行跨进程通信7. 适用于 HAL 的 AIDL8. Android Hal AIDL 编译调试9. 高版本Android (AIDL HAL) 沿用HIDL方…...
十、数据库day02--SQL语句01
文章目录 一、新建查询1.查询窗口的开启方法2. 单语句运行方法 二、数据库操作1.创建数据库2. 使用数据库3. 修改数据库4. 删除数据库和查看所有数据库5. 重点:数据库备份5.1 应用场景5.2 利用工具备份备份操作还原操作 5.3 扩展:使用命令备份 三、数据表…...
基于Atlas 800I A2 + Ubuntu 22.04 LTS 离线部署神州鲲泰问学一体机平台
一.环境信息 1.1.硬件信息 Atlas 800I A2 1.2.操作系统 版本: cat /etc/os-release PRETTY_NAME"Ubuntu 22.04 LTS" NAME"Ubuntu" VERSION_ID"22.04" VERSION"22.04 (Jammy Jellyfish)" VERSION_CODENAMEjammy IDubun…...
Shell脚本-变量是什么
在Shell脚本编程中,变量是一个非常基础且重要的概念。它们用于存储数据,并可以在整个脚本中引用这些数据来执行各种操作。理解如何定义、使用和管理变量是编写有效Shell脚本的关键。本文将详细介绍Shell脚本中的变量,包括其基本概念、类型以及…...
MCP 协议:AI 世界的 “USB-C 接口”,开启智能交互新时代
MCP协议:AI世界的“USB-C接口”,开启智能交互新时代 在AI技术飞速发展的今天,不同AI模型、应用与设备之间的交互和协同需求愈发迫切。就像USB-C接口统一了电子设备的数据传输与充电标准一样,**MCP协议(Model Communic…...
服务器的算力已经被被人占用了,我如何能“无缝衔接”?
今天遇到一个问题,服务器已经被别人占用了,我又不知道什么时候他能结束,因此很难去训练自己的模型,隔一会去看看别人是否结束又太麻烦,于是便可以写这个脚本文件来自动检测服务器是否空闲,一有空闲就可以自…...
大数据面试问答-批处理性能优化
1. 数据存储角度 1.1 存储优化 列式存储格式:使用Parquet/ORC代替CSV/JSON,减少I/O并提升压缩率。 df.write.parquet("hdfs://path/output.parquet")列式存储减少I/O的核心机制: 列裁剪(Column Pruning) …...
浅析数据库面试问题
以下是关于数据库的一些常见面试问题: 一、基础问题 什么是数据库? 数据库是按照数据结构来组织、存储和管理数据的仓库。SQL 和 NoSQL 的区别是什么? SQL 是关系型数据库,使用表结构存储数据;NoSQL 是非关系型数据库,支持多种数据模型(如文档型、键值对型等)。什么是…...
Android 12.0 framework实现对系统语言切换的功能实现
1.前言 在12.0的系统rom定制化开发过程中,在定制某些接口的过程中,需要通过系统提供接口,然后实现对系统语言的切换 功能实现,接下来分析下系统中关于系统语言切换的相关功能 2.framework实现对系统语言切换的功能实现的核心类 frameworks/base/core/java/android/app/IA…...
实时直播弹幕系统设计
整个服务读多写少,读写比例大概几百比1. 如果实时性要求高的话,可以采用长连接模式(轮询的话,时效性不好,同时对于评论少的直播间可能空转) websocket 和 SSE架构 只要求服务端推送的话,可以…...
[Java · 初窥门径] Java 语言初识
🌟 想系统化学习 Java 编程?看看这个:[编程基础] Java 学习手册 0x01:Java 编程语言简介 Java 是一种高级计算机编程语言,它是由 Sun Microsystems 公司(已被 Oracle 公司收购)于 1995 年 5 …...
【SQL Server】数据探查工具1.0研发可行性方案
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 想抢先解锁数据自由的宝子,速速戳我!评论区蹲一波 “蹲蹲”,揪人唠唠你的超实用需求! 【SQL Server】数据探查工具1.0研发可行性方案…...
谓词——C++
1.一元谓词 1.定义 2.案例 查找容器有没有大于五的数字 #include<stdio.h> using namespace std; #include<string> #include<vector> #include<set> #include <iostream> class myfind { public:bool operator()(int a){return a > 5;} …...
『前端样式分享』联系我们卡片式布局 自适应屏幕 hover动效 在wikijs中使用 (代码拿来即用)
目录 预览效果分析要点响应式网格布局卡片样式:阴影和过渡效果 代码优化希望 长短不一的邮箱地址在左右居中的同时,做到左侧文字对齐(wikijs可用)总结 欢迎关注 『前端布局样式』 专栏,持续更新中 欢迎关注 『前端布局样式』 专栏,持续更新中…...
Python PDF 转 Markdown 工具库对比与推荐
根据最新评测及开源社区实践,以下为综合性能与适用场景的推荐方案: 1. Marker 特点: 转换速度快,支持表格、公式(转为 LaTeX)、图片提取,适配复杂排版文档。依赖 PyTorch,…...
MySQL 缓存机制全解析:从磁盘 I/O 到性能优化
MySQL 缓存机制全解析:从磁盘 I/O 到性能优化 MySQL 的缓存机制是提升数据库性能的关键部分,它通过多级缓存减少磁盘 I/O 和计算开销,从而提高查询和写入的效率。 1. 为什么需要缓存? 数据库的性能瓶颈通常集中在磁盘 I/O 上。…...
1.1 设置电脑开机自动用户登录exe开机自动启动
本文介绍两个事情: 1.Windows如何开机自动登录系统(不用输密码) 2. 应用程序(.exe)如何开机自动启动 详细解释如下: 一、Windows如何开机自动登录系统(不用输密码) 设备上的工控机,如果开机后都需要操作人员输入密码&…...
