【C++】set
目录1. 引入从序列式到关联式容器2. set 的设计3. 核心接口3.1 构造函数 (Constructor)3.2 迭代器操作 (Iterator)3.3 容量操作 (Capacity)3.4 修改与查询操作 (Modifiers Operations)4. 核心操作4.1 插入与遍历自动去重排序4.2 查找与区间操作4.3 multiset不去重的变体5. 深度剖析底层引擎为什么是红黑树5.1 放弃 AVL 树的原因5.2 红黑树的妥协与优势5.3 迭代器底层的精妙设计附录基于红黑树封装自定义 set1. 引入从序列式到关联式容器在 C STL 中vector、list、deque等被称为序列式容器其底层是线性的数据结构存储的是元素本身。而为了解决海量数据下的高效率检索问题STL 引入了关联式容器。关联式容器的核心在于存储的是key, value结构的键值对。在底层键值对通过std::pair结构体实现包含代表键值的key(即first) 和对应信息的value(即second)。// STL 中键值对的底层定义templateclassT1,classT2structpair{typedefT1 first_type;typedefT2 second_type;T1 first;T2 second;pair():first(T1()),second(T2()){}pair(constT1a,constT2b):first(a),second(b){}};2. set 的设计根据底层结构的不同关联式容器分为树型结构如set、map和哈希结构。set作为树形关联容器的代表其设计具有以下核心特征真正的存储结构表面上set只对外暴露value但其底层实际存放的是由value, value构成的键值对。元素天然有序且唯一set内部根据特定的严格弱排序准则默认按小于升序对元素进行排序且每个value必须唯一。元素绝对禁止修改constset中的元素在容器中总是const的。深度思考为什么不允许修改因为set的底层是二叉搜索树如果允许修改结点的key会直接破坏树的有序性与严格弱排序准则导致整棵树失效。时间复杂度依靠平衡树支撑查找、插入和删除的时间复杂度均严格稳定在O ( log ⁡ 2 N ) O(\log_2 N)O(log2​N)。3. 核心接口3.1 构造函数 (Constructor)函数声明功能介绍set (const Compare comp Compare(), const Allocator Allocator() );构造空的 setset (InputIterator first, InputIterator last, ...);用[first, last)区间中的元素构造 setset (const setKey,Compare,Allocator x);set 的拷贝构造3.2 迭代器操作 (Iterator)函数声明功能介绍iterator begin()/iterator end()返回正向迭代器begin指向首元素end指向尾元素下一个位置const_iterator cbegin()/cend()返回const版本的正向迭代器reverse_iterator rbegin()/rend()返回反向迭代器rbegin即endrend即beginconst_reverse_iterator crbegin()/crend()返回const版本的反向迭代器3.3 容量操作 (Capacity)函数声明功能介绍bool empty() const检测 set 是否为空空返回true否则返回falsesize_type size() const返回 set 中有效元素的个数3.4 修改与查询操作 (Modifiers Operations)函数声明功能介绍pairiterator,bool insert(const value_type x)在 set 中插入元素 x返回该元素位置, 是否插入成功若已存在则返回 falseiterator erase (const_iterator position)删除 position 位置上的元素size_type erase (const key_type x)删除 set 中值为 x 的元素返回删除的元素个数iterator erase (const_iterator first, const_iterator last)删除 set 中[first, last)区间中的元素void swap (setKey, Allocator Compare, st)交换两个 set 中的元素void clear ()将 set 中的元素清空iterator find (const key_type x) const返回 set 中值为 x 的元素的位置迭代器找不到则返回end()size_type count (const key_type x) const返回 set 中值为 x 的元素的个数对于 set 只能是 0 或 14. 核心操作4.1 插入与遍历自动去重排序在set中插入元素时无需显式构造键值对直接传入value即可。#includeiostream#includesetusingnamespacestd;intmain(){// 去重 排序setints;s.insert(5);s.insert(2);s.insert(7);s.insert(4);s.insert(9);s.insert(9);// 重复插入无效s.insert(9);s.insert(1);autoits.begin();while(it!s.end()){cout*it ;it;}coutendl;// 范围 for 遍历for(autoe:s){coute ;}coutendl;return0;}4.2 查找与区间操作必须认清算法库中的std::find与set::find的本质区别// 1. 算法库的 find底层暴力遍历时间复杂度 O(N)autopos1find(s.begin(),s.end(),x);// 2. set 成员函数 find利用红黑树查找时间复杂度 O(log_2 N)autopos2s.find(x);对于区间操作set提供了lower_bound返回≥ \ge≥目标的迭代器和upper_bound返回 目标的迭代器极大地简化了左闭右开[first, last)区间的删除操作。intmain(){setintmyset;setint::iterator itlow,itup;for(inti1;i10;i)myset.insert(i*10);// 10 20 30 40 50 60 70 80 90itlowmyset.lower_bound(30);// 30itupmyset.upper_bound(60);// 60// 删除 [30, 60]myset.erase(itlow,itup);// 剩余: 10 20 70 80 90for(setint::iterator itmyset.begin();it!myset.end();it)cout *it;coutendl;return0;}4.3 multiset不去重的变体intmain(){multisetints;s.insert(1);s.insert(10);s.insert(15);s.insert(14);s.insert(14);s.insert(14);for(autow:s){coutw ;}coutendls.count(14);return0;}如果业务场景仅需排序而不需要去重可以使用multiset。其接口与set基本一致底层同样存放value, value但允许元素重复。此时调用count(x)能够返回元素出现的实际次数而不再局限于 0 或 1。5. 深度剖析底层引擎为什么是红黑树set和map的底层均为红黑树 (Red-Black Tree)而不是 AVL 树。5.1 放弃 AVL 树的原因AVL 树是绝对平衡的二叉搜索树要求每个结点的左右子树高度差绝对值不超过 1。这保证了极高的查询效率O ( log ⁡ 2 N ) O(\log_2 N)O(log2​N)。但是在频繁增删结点的场景下AVL 树为了维持这种绝对平衡需要进行大量的旋转操作甚至在删除时旋转可能持续到根结点性能开销极大。5.2 红黑树的妥协与优势红黑树通过颜色约束牺牲了部分平衡性来换取更少旋转次数每个结点不是红色就是黑色。根结点必须是黑色。不能有连在一起的红色结点。每条路径上的黑色结点数目必须相同。这些性质确保了红黑树的最长路径不会超过最短路径的两倍达成了一种“近似平衡”。它的增删改查时间复杂度依然是O ( log ⁡ 2 N ) O(\log_2 N)O(log2​N)但由于旋转次数远少于 AVL 树在实际应用如 C STL、Linux 内核中具有更高的综合性能。5.3 迭代器底层的精妙设计STL 规定begin()和end()构成前闭后开的区间。在中序遍历红黑树时begin()应当是最小结点最左侧结点那end()最大结点的下一个位置应该指向哪里不能简单设为nullptr因为还要支持对end()迭代器进行--操作找回最后一个元素。STL 的红黑树实现中巧妙地增加了一个黑色的头结点 (header)header-_pParent指向红黑树真实的root。header-_pLeft指向树中最小的结点即begin()。header-_pRight指向树中最大的结点。end()迭代器直接指向这个header结点。这种设计完美闭环了整棵树的迭代逻辑。附录基于红黑树封装自定义 set为了证明底层结构与表层 API 的关系我们可以通过复用泛型红黑树RBTree来模拟实现一个完整的set。#includefunctional// 为了引入 std::lessnamespacebit{// 增加 Compare 模板参数默认使用 lessKtemplateclassK,classComparestd::lessKclassset{typedefK ValueType;structKeyOfValue{constKoperator()(constValueTypekey)const// 注意加 const{returnkey;}};// 将 Compare 也传给底层的红黑树typedefRBTreeK,ValueType,KeyOfValue,CompareRBTree_t;public:// 关键set 的迭代器统一使用红黑树的 const 迭代器typedeftypenameRBTree_t::ConstIterator iterator;typedeftypenameRBTree_t::ConstIterator const_iterator;public:set(){}// 提供 const 版本的迭代器接口iteratorbegin()const{return_t.Begin();}iteratorend()const{return_t.End();}size_tsize()const{return_t.Size();}boolempty()const{return_t.Empty();}// 注意底层 Insert 如果返回 pairRBTree_t::Iterator, bool// 这里可能需要做一个隐式或显式的转换转成 pairiterator, boolpairiterator,boolinsert(constValueTypedata){return_t.Insert(data);}voidclear(){_t.Clear();}iteratorfind(constKkey)const// 提供 const 版本的 find{return_t.Find(key);}private:RBTree_t _t;};}

相关新闻

Cursor Pro完整功能免费使用终极指南:解锁无限AI编程助手

Cursor Pro完整功能免费使用终极指南:解锁无限AI编程助手

Cursor Pro完整功能免费使用终极指南:解锁无限AI编程助手 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your …

2026/10/18 4:09:25 阅读更多 →
如何在Windows 11上玩转经典局域网游戏:IPXWrapper终极解决方案

如何在Windows 11上玩转经典局域网游戏:IPXWrapper终极解决方案

如何在Windows 11上玩转经典局域网游戏:IPXWrapper终极解决方案 【免费下载链接】ipxwrapper 项目地址: https://gitcode.com/gh_mirrors/ip/ipxwrapper 还在为Windows 11上无法联机玩《星际争霸》《英雄无敌3》等经典游戏而烦恼吗?IPXWrapper就…

2026/10/18 4:09:35 阅读更多 →
Agentic AI时代:从工具到协作伙伴的提示设计变革

Agentic AI时代:从工具到协作伙伴的提示设计变革

1. 从工具到同事:Agentic AI时代提示设计的范式转移清晨8点15分,我像往常一样打开电脑准备开始一天的工作。但与以往不同的是,这次我面对的不再是一个等待指令的AI工具,而是一位具备自主决策能力的"数字同事"。我输入了…

2026/10/18 4:10:26 阅读更多 →

最新新闻

用A4纸拼出广告牌:低成本大幅面打印的完整工作流与创意实践

用A4纸拼出广告牌:低成本大幅面打印的完整工作流与创意实践

最近路过街头时看到一台摆在路边的打印机,身边围了一圈人,正一张接一张地往外吐A4纸,旁边贴了半面墙的成品。凑近一看才发现,那根本不是一张普通的"打印演示",而是在现场打印一整个广告牌——用最普通的A4纸…

2026/10/19 20:56:16 阅读更多 →
极小函数依赖集求解算法:拆、删、消三步与手算例题

极小函数依赖集求解算法:拆、删、消三步与手算例题

函数依赖的极小化,大概是数据库原理课里最让人“背得下定义却下不了笔”的考点了。提到极小函数依赖集,多数人都能背出三条:右部单属性、没有冗余依赖、没有冗余属性。可真给你一张函数依赖集F,让你求Fmin,很多人第一步…

2026/10/19 20:55:12 阅读更多 →
数据可视化全流程实操:Python+Seaborn从选图到避坑

数据可视化全流程实操:Python+Seaborn从选图到避坑

某高校的数据能力提升营走到第7天,主题就是数据可视化。这个营我们内部一直叫它“疏锦行”,名字听着文艺,实际任务却很务实:一周时间,从数据采集一路练到统计建模,而第7天这一天,不带任何新模型…

2026/10/19 20:55:12 阅读更多 →
线性回归从手写梯度下降到sklearn实战:原理、特征工程与过拟合避坑

线性回归从手写梯度下降到sklearn实战:原理、特征工程与过拟合避坑

如果你只会调包,那线性回归等于没学会作为数据分析或者机器学习入门的第一课,线性回归几乎是所有人都会遇到的第一个模型。我见过太多人上来就from sklearn.linear_model import LinearRegression,然后fit、predict、打印个 R 就算完事。真要…

2026/10/19 20:55:12 阅读更多 →
达梦数据库大小写敏感机制详解:从原理到实践避坑

达梦数据库大小写敏感机制详解:从原理到实践避坑

1. 项目概述:达梦大小写敏感到底是个什么事做数据库开发或者运维的朋友,只要是第一次接触达梦数据库,十有八九会遇到一个让人摸不着头脑的现象:明明建表时写的是 "USER_INFO",去查询的时候写 "user_inf…

2026/10/19 20:52:07 阅读更多 →
C++ std::bind实战:占位符、引用陷阱与lambda取舍

C++ std::bind实战:占位符、引用陷阱与lambda取舍

1. 我为什么又回头研究bind:代码里最不起眼的粘连剂搞C时间一长,你会发现真正让代码"绕起来"的往往不是那些宏大设计,而是一堆不起眼的小工具。std::bind就是其中之一。最近接手的某调度模块里,回调参数七零八落&#x…

2026/10/19 20:52:07 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →