【STL】set

news2025/4/16 21:50:46

C C C++ S T L STL STL 标准库中, s e t set set 是一个关联式容器,表示一个集合,用于存储唯一元素的容器。 s e t set set 中的元素会自动按照一定的顺序排序(默认情况下是升序)。这意味着在 s e t set set 中不能插入重复的元素,因为重复的元素会被忽略。

文章目录

  • 前言 —— 关联式容器
  • 一、set 的介绍
  • 二、set 的使用(常用接口)
    • 1. 常见构造
    • 2. iterator 的使用
    • 3. 增删查
    • 4. multiset 和 set 的差异
  • 三、set 的模拟实现
  • 总结


前言 —— 关联式容器

关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构,两个位置有紧密的关联关系,交换一下,他的存储结构就被破坏了。

关联式容器中的元素是按关键字 k e y key key)来保存和访问的。

C C C++ S T L STL STL 中主要提供了以下关联式容器

  1. s e t / m u l t i s e t set/multiset set/multiset集合 / / /多重集合

  2. m a p / m u l t i m a p map/multimap map/multimap映射 / / /多重映射

  3. u n o r d e r e d _ s e t / u n o r d e r e d _ m u l t i s e t unordered\_set/unordered\_multiset unordered_set/unordered_multiset无序集合 / / /多重无序集合

  4. u n o r d e r e d _ m a p / u n o r d e r e d _ m u l t i m a p unordered\_map/unordered\_multimap unordered_map/unordered_multimap无序映射 / / /多重无序映射

S T L STL STL 标准库中的 m a p map map s e t set set 底层是用红黑树实现的,红黑树是一颗平衡二叉搜索树

s e t set set k e y key key 搜索场景的结构, m a p map map k e y / v a l u e key/value key/value 搜索场景的结构。


一、set 的介绍

s e t set set 系列根据容器是否支持插入相同元素而分为了 s e t set set(集合)和 m u l t i s e t multiset multiset(多重集合)。

s e t set set 其实就是按特定顺序存储唯一元素的容器

在这里插入图片描述

m u l t i s e t multiset multiset 其实就是按特定顺序存储元素的容器,其中多个元素可以具有等效的值

在这里插入图片描述

由于最常用的还是 s e t set set 容器,因此这里主要介绍的是 s e t set set,而 m u l t i s e t multiset multiset s e t set set 只有在一些地方有略微的不同,稍注意一下即可。

s e t set set 的声明如下:

template < class T, 					// set::key_type/value_type
		   class Compare = less<T>, 	// set::key_compare/value_compare
		   class Alloc = allocator<T> 	// set::allocator_type
		 > class set;
  1. T T T 就是 s e t set set 底层关键字的类型。

  2. s e t set set 默认要求 T T T 支持小于比较less<T>升序排序),如果不支持或者想按自己的需求走可以自行实现仿函数传给第二个模板参数。

  3. s e t set set 底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第三个模板参数。

注意:一般情况下,我们都不需要传后两个模版参数。

s e t set set 底层是用红黑树实现的,增删查效率是 O ( l o g N ) O(logN) O(logN)迭代器遍历是走的搜索树的中序,所以是有序的。


二、set 的使用(常用接口)

下面只列举了 s e t set set 最常用的几个接口,更多详细信息可以自行查官方文档: s e t set set

1. 常见构造

构造 ( c o n s t r u c t o r ) (constructor) (constructor) 函数声明接口说明
s e t ( ) set() set()无参默认构造
s e t ( c o n s t   s e t &   x ) set(const\ set\&\ x) set(const set& x)拷贝构造
s e t ( I n p u t I t e r a t o r   f i r s t , I n p u t I t e r a t o r   l a s t ) set(InputIterator\ first, InputIterator\ last) set(InputIterator first,InputIterator last)使用迭代器区间构造
s e t ( i n i t i a l i z e r _ l i s t < v a l u e _ t y p e > i l ) set (initializer\_list<value\_type> il) set(initializer_list<value_type>il)使用 i n i t i a l i z e r initializer initializer 列表构造
  1. 无参默认构造:
set<int> s1;					// 升序
set<int, greater<int>> s2;		// 降序
  1. 拷贝构造:
set<int> s = { 3,1,2,4,5 };
set<int> s1(s);					// 升序
set<int, greater<int>> s2 = s;	// 降序
  1. 迭代器区间构造:
int a[] = { 3,1,2,4,5 };
vector<int> v = { 3,1,2,4,5 };
set<int> s1(a ,a + 5);							// 升序
set<int, greater<int>> s2(v.begin() ,v.end());	// 降序
  1. i n i t i a l i z e r initializer initializer 列表构造:
set<int> s1 = { 3,1,2,4,5 };				// 升序
set<int, greater<int>> s2({ 3,1,2,4,5 });	// 降序

2. iterator 的使用

i t e r a t o r iterator iterator 的使用接口说明
b e g i n ( ) begin() begin() + + + e n d ( ) end() end()正向迭代器( i t e r a t o r iterator iterator
r b e g i n ( ) rbegin() rbegin() + + + r e n d ( ) rend() rend()反向迭代器( r e v e r s e _ i t e r a t o r reverse\_iterator reverse_iterator
  1. s e t set set 的迭代器支持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是二叉搜索树迭代器遍历走的是中序遍历

  2. 支持迭代器就意味着支持范围 f o r for for

  3. s e t set set i t e r a t o r iterator iterator c o n s t _ i t e r a t o r const\_iterator const_iterator不支持迭代器修改数据,修改关键字数据,就破坏了底层搜索树的结构。

  4. s e t set set 的迭代器是一个双向迭代器iterator -> a bidirectional iterator to const value_type
    在这里插入图片描述

set<int> s = { 3,5,4,2,1 };

// 1.正向迭代器
auto it = s.begin();
while (it != s.end())
{
	cout << *it << " ";
	++it;
}
cout << endl;

// 2.反向迭代器
auto rit = s.rbegin();
while (rit != s.rend())
{
	cout << *rit << " ";
	++rit;
}
cout << endl;

// 3.范围for
for (auto& e : s)
{
	cout << e << " ";
}
cout << endl;

输出:

1 2 3 4 5
5 4 3 2 1
1 2 3 4 5

3. 增删查

s e t set set 增删查接口说明
i n s e r t insert insert插入 v a l val val 数据
e r a s e erase erase删除 v a l val val 数据
f i n d find find查找 v a l val val,返回 v a l val val 位置的迭代器(没找到返回 e n d ( ) end() end()
c o u n t count count查找 v a l val val,返回 v a l val val 的个数
l o w e r _ b o u n d lower\_bound lower_bound返回大于等于 v a l val val 位置的迭代器
u p p e r _ b o u n d upper\_bound upper_bound返回大于 v a l val val 位置的迭代器
  1. 插入数据(insert):
vector<int> v = { 1,2,5 };
set<int> s;

// 1.直接插入
s.insert(3);
// 2.指定位置插入
s.insert(s.begin(), 4);
// 3.迭代器区间插入
s.insert(v.begin(), v.end());
// 4.initializer插入
s.insert({ 6,7,8 });

for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 7 8
  1. 查找 + 删除数据(find + erase):
set<int> s = { 1,2,3,4,5,6,7,8 };

// 1.指定位置删除
s.erase(s.begin());
// 2.指定数据删除
s.erase(5);
// 3.迭代器区间删除
auto it = s.find(4);		// 返回值对应的迭代器(没找到就返回s.end())
if(it != s.end())
	s.erase(s.begin(),it);	// 前闭后开[s.begin(),it)

for (const auto& e : s) cout << e << " "; cout << endl;

输出:

4 6 7 8
  1. lower_bound / upper_bound
set<int> s = { 1,2,3,4,5,6,7,8 };

auto it1 = s.lower_bound(3);	// 返回第一个值 >= 3的迭代器
auto it2 = s.upper_bound(7);	// 返回第一个值 > 3的迭代器

// 删除[3,7]区间的数据
s.erase(it1,it2);

for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 8

4. multiset 和 set 的差异

m u l t i s e t multiset multiset s e t set set 的使用基本完全类似,主要区别点在于 m u l t i s e t multiset multiset 支持值冗余

那么 i n s e r t / f i n d / c o u n t / e r a s e insert/find/count/erase insert/find/count/erase 都围绕着支持值冗余有所差异:

  1. i n s e r t insert insert 可以插入相同的值
multiset<int> s = { 1,2,3,4,5,6,7,8 };
s.insert(6);
s.insert(6);
s.insert(6);

for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 6 6 6 7 8
  1. 如果要查找的 x x x 有多个值, f i n d find find 会返回中序的第一个
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };

auto it = s.find(6);
while (it != s.end() && *it == 6)
{
	cout << *it << " ";
	++it;
}
cout << endl;

输出:

6 6 6 6
  1. c o u n t count count 会返回 x x x 的实际个数:
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };

cout << "6的个数:" << s.count(6) << endl;
cout << "9的个数:" << s.count(9) << endl;

输出:

6的个数:4
9的个数:0
  1. e r a s e erase erase 指定值删除时,会删除所有的 x x x
multiset<int> s = { 1,2,3,4,5,6,6,6,6,7,8 };

// 1.指定迭代器删除只会删除一个值
auto it = s.find(6);
s.erase(it);
for (const auto& e : s) cout << e << " "; cout << endl;

// 2.指定值删除会删除所有的值
s.erase(6);
for (const auto& e : s) cout << e << " "; cout << endl;

输出:

1 2 3 4 5 6 6 6 7 8
1 2 3 4 5 7 8

三、set 的模拟实现


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入剖析C++中 String 类的模拟实现

目录 引言 一、基础框架搭建 成员变量与基本构造函数 析构函数 二、拷贝与赋值操作 深拷贝的拷贝构造函数 赋值运算符重载 三、字符串操作功能实现 获取字符串长度 字符串拼接 字符串比较 字符访问 四、迭代器相关实现&#xff08;简单模拟&#xff09; 迭代器类型…

STL之priority_queue的用法与实现

目录 1. priority_queue的介绍 1.1. priority_queue的概念 1.2. priority_queue的特点 2. 仿函数 2.1. 仿函数的概念 2.2. 仿函数的应用 2.3 仿函数的灵活性 3. priority_queue的用法 4. 模拟实现priority_queue 4.1. 插入 4.2. 删除 5. 源码 priority_…

散户使用算法交易怎么做?

智能算法交易是量化交易里面最常见的一种&#xff0c;也是大多数散户被套住的股票&#xff0c;想要解套&#xff0c;降低成本最直接有效的方式。但是往往这种波动速度小&#xff0c;担心速度跟不上的情况&#xff0c;我们就要叠加快速通道。 第一&#xff1a;算法交易的应用场…

mongodb 安装配置

1.官网下载地址&#xff1a;MongoDB Community Download | MongoDB 2.解压包安装&#xff1a;https://pan.baidu.com/s/1Er56twK9UfxoExuCPlJjhg 提取码: 26aj 3.配置环境&#xff1a; &#xff08;1&#xff09;mongodb安装包位置&#xff1a; &#xff08;2&#xff09;复…

榕壹云酒水定制系统:基于THinKPHP+MySQL+UniApp打造数字化时代的个性化购酒新体验

数字化浪潮下的酒水定制新机遇 在消费升级与个性化需求崛起的背景下,传统酒水行业正面临数字化转型的迫切需求。为此,我们团队基于ThinkPHP+MySQL+UniApp技术栈,开发了一套榕壹云酒水定制系统,旨在通过数字化手段解决消费者个性化购酒痛点,为酒类品牌提供全链路数字化解决…

Leetcode——137 260找出只出现一次的数

文章目录 找出只出现一次的数引入Leetcode 260Leetcode 137 找出只出现一次的数 对于数组中有一类题&#xff0c;即某些数据在数组中只出现一遍&#xff0c;需要我们找出&#xff0c;今天我们来看看这个类型的题。 引入 想必大家应该见过这么一道题&#xff1a; 现给定一个数…

OpenTiny使用指南

最近项目里用到了一个新的组件库——OpenTiny&#xff0c;但是官方文档的使用指南的描述很复杂&#xff0c;花了一些时间尝试才正常使用。下面是一个使用步骤的描述&#xff0c;可放心食用&#xff1a; 一、安装 TinyVue 组件库同时支持 Vue 2.0 和 Vue 3.0 框架&#xff0c;…

KingbaseES之KDts迁移SQLServer

项目适配迁移SQLServer至金仓,今天写写KDts-WEB版迁移工具迁移SQLServer至KingbaseES的步骤,以及迁移注意事项. SQLServer版本:SQLServer2012 KingbaseES版本:V009R004C011(SQLServer兼容版) --1.进入数据库客户端工具KDTS工具目录&#xff0c;启动KDts服务&#xff1a; [king…

代码随想录动态规划part02

动态规划part02 62.不同路径 代码随想录 视频讲解&#xff1a;动态规划中如何初始化很重要&#xff01;| LeetCode&#xff1a;62.不同路径_哔哩哔哩_bilibili 递归法 动态规划&#xff0c;当前状态是由上一个状态转化来的 这里初始化错误了&#xff0c;想法是对的右一和…

详解如何复现DeepSeek R1:从零开始利用Python构建

DeepSeek R1 的整个训练过程&#xff0c;说白了就是在其基础模型&#xff08;也就是 deepseek V3&#xff09;之上&#xff0c;用各种不同的强化学习方法来“雕琢”它。 咱们从一个小小的本地运行的基础模型开始&#xff0c;一边跟着 DeepSeek R1 技术报告 的步骤&#xff0c;…

Java集合框架 源码分析 迭代器 并发修改异常底层原理

迭代器 Java中的Iterator&#xff08;迭代器&#xff09;是集合框架中用于遍历容器元素的统一接口&#xff0c;提供了一种标准化的元素访问方式&#xff0c;无需依赖具体集合类型的实现细节。以下是其核心要点&#xff1a; 一、核心方法与使用步骤 获取迭代器 通过集合的 it…

Cannot find module ‘vue‘ or its corresponding type declarations

在使用vue3vite创建新的工程时&#xff0c;在新增.vue文件时会出现Cannot find module vue这个错误。 只需要我们在项目中的.d.ts文件中添加以下代码即可 declare module *.vue {import { defineComponent } from vue;const component: ReturnType<typeof defineComponent&…

【Python爬虫】详细工作流程以及组成部分

目录 一、Python爬虫的详细工作流程 确定起始网页 发送 HTTP 请求 解析 HTML 处理数据 跟踪链接 递归抓取 存储数据 二、Python爬虫的组成部分 请求模块 解析模块 数据处理模块 存储模块 调度模块 反爬虫处理模块 一、Python爬虫的详细工作流程 在进行网络爬虫工…

欧拉服务器操作系统部署deekseep(Ollama+DeekSeep+open WebUI)

​​一、解压并安装 Ollama​​ # 1. 解压文件&#xff08;默认会得到一个二进制文件&#xff09; tar -xzvf ollama-linux-amd64.tgz# 2. 将二进制文件安装到系统路径 sudo mv ollama /usr/local/bin/ sudo chmod x /usr/local/bin/ollama# 3. 验证安装 ollama --version链接…

#4 我们为什么使用物联网? 以及 物联网的整体结构

设备不物联是否可以&#xff1f; 答案 是可以的&#xff0c;从项目实战的角度&#xff0c;还是有很多包括分拣&#xff0c;控制&#xff0c;检测等应用是分立的&#xff0c;这个和成本&#xff0c;场景&#xff0c;客户接受度等因素有关。 局部看&#xff0c;一些系统的确很简…

3D版的VLA——从3D VLA、SpatialVLA到PointVLA(不动VLM,仅动作专家中加入3D数据)

前言 之前写这篇文章的时候&#xff0c;就想解读下3D VLA来着&#xff0c;但一直因为和团队并行开发具身项目&#xff0c;很多解读被各种延后 更是各种出差&#xff0c;比如从25年3月下旬至今&#xff0c;连续出差三轮&#xff0c;绕中国半圈&#xff0c;具身占八成 第一轮 …

linux Shell编程之循环语句(三)

目录 一. for 循环语句 1. for语句的结构 2. for 语句应用示例 (1) 根据姓名列表批量添加用户 (2) 根据 IP 地址列表检查主机状态 二. 使用 while 循环语句 1. while 语句的结构 2. while 语句应用示例 (1) 批量添加规律编号的用户 (2) 猜价格游戏 三. until 循环语…

C#容器源码分析 --- Queue<T>

Queue<T> 是 System.Collections.Generic 命名空间下的先进先出&#xff08;FIFO&#xff09;动态集合&#xff0c;其核心实现基于​​循环数组​​&#xff0c;通过维护头尾指针实现高效入队和出队操作。 .Net4.8 Queue<T>源码地址&#xff1a;queue.cs (microso…

ViT 模型讲解

文章目录 一、模型的诞生背景1.1 背景1.2 ViT 的提出&#xff08;2020年&#xff09; 二、模型架构2.1 patch2.2 模型结构2.2.1 数据 shape 变化2.2.2 代码示例2.2.3 模型结构图 2.3 关于空间信息 三、实验3.1 主要实验3.2 消融实验 四、先验问题4.1 归纳偏置4.2 先验or大数据&…

IntelliJ IDEA 中安装和使用通义灵码 AI 编程助手教程

随着人工智能技术的发展&#xff0c;AI 编程助手逐渐成为提升开发效率的强大工具。通义灵码是阿里云推出的一款 AI 编程助手&#xff0c;它能够帮助开发者实现智能代码补全、代码解释、生成单元测试等功能&#xff0c;极大地提升了编程效率和代码质量。 IntelliJ IDEA 是一款广…