当前位置: 首页 > news >正文

C++笔记 STL——set

在 C++ 的标准模板库(STL)中,set是一个核心的关联式容器,它以自动排序元素唯一性为核心特性,为开发者提供了高效的元素存储、查找与管理方案。不同于数组、vector 这类顺序容器,set不关注元素的插入顺序,而是专注于元素的有序性和唯一性,是处理去重、排序、快速查找等场景的理想工具。

本文将从核心特性、底层原理、基础用法、常用操作、适用场景及注意事项等方面,全面讲解 STL 中的set

一、set 的核心特性

  1. 元素唯一性set中不允许存储重复元素,插入重复值时,容器会自动忽略该操作,保证容器内元素无重复。
  2. 自动排序set默认按照升序对元素进行排序(可自定义排序规则),无需手动调用排序算法。
  3. 不可修改元素set中的元素本质是常量,不能直接修改元素值(修改会破坏排序规则),若需修改,必须先删除旧元素,再插入新元素。
  4. 高效操作:基于平衡二叉树(红黑树)实现,查找、插入、删除操作的时间复杂度均为 \(O(log n)\),远优于顺序容器的线性查找。

二、set 的底层原理

set的底层实现是红黑树(一种自平衡的二叉查找树)。红黑树的特性保证了set始终保持有序,且能在对数时间内完成核心操作:

自平衡:避免树结构退化,保证操作效率稳定;

有序性:树的中序遍历结果即为元素的排序结果,天然支持有序遍历。

这也是set能实现自动排序和高效操作的核心原因。

三、set 的基础用法

使用set必须包含头文件<set>,且属于std命名空间,基础代码框架如下:

1. 头文件与命名空间

#include <iostream> #include <set> // 必须包含的头文件 using namespace std;

2. 定义与初始化

set是模板类,需指定存储元素的类型,支持多种初始化方式:

// 1. 空 set 定义 set<int> s1; // 2. 列表初始化(C++11及以上) set<int> s2 = {3, 1, 4, 1, 5}; // 重复元素1会被自动去重,最终元素:1,3,4,5 // 3. 拷贝初始化 set<int> s3(s2); // 4. 自定义排序规则(降序) set<int, greater<int>> s4 = {3, 1, 4}; // 元素:4,3,1

3. 插入元素

使用insert()方法插入元素,支持单个插入、批量插入:

set<int> s; // 单个插入 s.insert(2); s.insert(1); s.insert(3); // 插入重复元素,自动忽略 s.insert(2); // 批量插入 int arr[] = {5, 4}; s.insert(arr, arr + 2);

4. 遍历元素

set支持迭代器遍历、范围 for 遍历两种常用方式:

// 方法1:迭代器遍历 set<int>::iterator it; for (it = s.begin(); it != s.end(); it++) { cout << *it << " "; // 输出:1 2 3 4 5 } // 方法2:范围for遍历(更简洁,C++11及以上) for (int num : s) { cout << num << " "; }

四、set 的常用成员函数

set提供了丰富的成员函数,覆盖增删改查、容量判断等核心操作,常用函数如下:

表格

函数功能
insert(val)插入元素val,自动去重 + 排序
erase(val)删除值为val的元素
erase(it)删除迭代器it指向的元素
find(val)查找元素val,返回指向该元素的迭代器;未找到则返回end()
count(val)统计元素val的个数(结果只能是 0 或 1,用于判断元素是否存在)
size()返回容器中元素的个数
empty()判断容器是否为空,空返回true,否则返回false
clear()清空容器中所有元素
begin()返回指向第一个元素的迭代器
end()返回指向最后一个元素下一个位置的迭代器

示例:核心操作实战

#include <iostream> #include <set> using namespace std; int main() { set<int> s = {10, 20, 30}; // 1. 查找元素 auto it = s.find(20); if (it != s.end()) { cout << "找到元素:" << *it << endl; } else { cout << "未找到元素" << endl; } // 2. 判断元素是否存在 if (s.count(15)) { cout << "15存在" << endl; } else { cout << "15不存在" << endl; } // 3. 删除元素 s.erase(10); // 删除值为10的元素 // 4. 查看大小 cout << "元素个数:" << s.size() << endl; // 输出:2 // 5. 清空容器 s.clear(); cout << "是否为空:" << s.empty() << endl; // 输出:1(true) return 0; }

五、set 的适用场景

set的特性决定了它的适用场景,核心用于:

  1. 自动去重:无需手动判断重复,直接插入即可保证元素唯一;
  2. 有序存储:需要数据始终保持有序,无需手动排序;
  3. 快速查找:频繁判断元素是否存在,效率远高于 vector;
  4. 去重 + 排序:同时需要去重和排序的场景(如统计不重复的分数、编号等)。

场景举例

统计学生的唯一学号;

过滤重复的文本关键词;

有序存储排行榜数据;

快速判断某个值是否在集合中。

六、set 与 multiset、unordered_set 的区别

STL 中还有两个与set相似的容器,三者对比如下:

  1. set:元素唯一,自动排序,底层红黑树;
  2. multiset允许重复元素,自动排序,底层红黑树;
  3. unordered_set:元素唯一,不排序,底层哈希表,查找速度更快(\(O(1)\))。

根据业务需求选择:需要有序选set,允许重复选multiset,追求极致查找效率选unordered_set

七、注意事项

  1. 不能直接修改set中的元素,必须先删后插;
  2. 插入自定义类型时,需要重载<运算符(否则set无法排序);
  3. 迭代器遍历的结果是有序的,不要依赖插入顺序;
  4. count()函数仅返回 0 或 1,用于判断元素存在即可。

总结

STL 中的set是一个有序、唯一、高效的关联式容器,依托红黑树实现了 \(O(log n)\) 级别的核心操作,完美适配去重、排序、快速查找等场景。它的用法简洁、功能强大,是 C++ 开发中处理集合类数据的首选工具之一。

掌握set的用法,能大幅简化代码逻辑,提升程序效率,是学习 STL 容器的重要一环。

http://www.jsqmd.com/news/720428/

相关文章:

  • 从viewBox到symbol:手把手教你用SVG搭建一套可复用的图标系统
  • Obsidian插件国际化实践指南:如何用正则匹配与动态注入技术实现插件界面汉化
  • CC-Switch_下载安装_配置流程_2026.4.28
  • “主动+量化”融合:一个程序员的视角
  • CPPM证书在国企有用吗?体制内认可度 - 众智商学院官方
  • Visual Syslog Server:Windows环境企业级日志集中管理终极解决方案
  • 冲孔链板提升机:选型逻辑与场景适配全科普 - 奔跑123
  • 5分钟掌握Electron-Vue:用Vue.js轻松构建跨平台桌面应用
  • 别再手动循环了!C++中vector<uint8_t>与原始数组互转的3种高效写法(附性能对比)
  • 红色系网络公司网站 官网源码 四网合一四端全支持
  • 深求·墨鉴部署案例:NVIDIA T4服务器上单卡并发5路OCR的算力优化实践
  • 知识竞赛策划全流程详解
  • 探索桌面萌宠的无限可能:BongoCat模型定制艺术揭秘
  • 国内农化领域瓶装灌装机厂家实力排行盘点 - 奔跑123
  • 如何零基础掌握Charticulator:免费图表设计工具完整指南
  • 2026最新火锅底料品牌/公司推荐!国内优质权威榜单发布,口碑出众成都福建四川等地品牌精选 - 十大品牌榜
  • 图片批量下载终极指南:3步快速部署高效图像采集工具
  • 2026FIC初赛-服务器部分WP
  • 用JavaScript手写一个斗地主残局破解器(附完整源码和递归算法详解)
  • Windows系统调校的艺术:Winhance中文版深度解析与实践指南
  • AI超级员工系统怎么选?这5个问答帮你避开90%的坑 - 速递信息
  • 从‘红字’到‘白屏’:深入浏览器控制台,彻底理解Promise错误捕获机制
  • AVAudioSession 核心实战:后台播放、听筒/扬声器切换与静音键适配全解析
  • R 4.5下microbiome+metagenomeSeq+mixOmics三库协同失效?——2024年首份跨平台多组学整合分析稳定性白皮书
  • 2026年浙江灭火设备厂家权威推荐,烟罩灭火设备/灶台灭火设备/食堂灭火设备/学校食堂灭火设备/厨房灶台灭火设备 - 品牌策略师
  • 基于Matlab的脑电信号处理系统设计与实现:GUI界面、时频域分析、预处理与分解
  • 保姆级教程:在Ubuntu 20.04上搞定ARM交叉编译工具链gcc-arm-8.3-2019.03
  • 山东兴德链条:深耕链板提升机制造 解决多行业爬坡输送痛点 - 奔跑123
  • 告别配对数据烦恼:用EnlightenGAN无监督增强夜间照片,实测效果与避坑指南
  • 为什么你的鸿蒙游戏发布越来越慢?