C++ 入门16:STL 容器之集合(set)与多重集合(multiset)

往期回顾:

C++ 入门13:异常处理-CSDN博客

C++ 入门14:STL 容器之向量(vector)-CSDN博客

C++ 入门15:STL 容器之列表(list)-CSDN博客


C++ 入门16:STL 容器之集合(set)与多重集合(multiset)

一、前言

在上一篇文章中,我们深入了解了列表(list)容器,一种双向链表,它在插入和删除元素方面表现卓越。今天我们学习另一种强大的 STL 容器:集合(set)和多重集合(multiset)。这两种容器提供了有序数据存储的功能,能够帮助我们在开发中处理各种需要排序和唯一性检查的场景。

二、STL 容器之集合

2.1、什么是集合(set)?

集合(Set)是一种非常特殊且强大的关联容器,它在数据结构和算法设计中占据重要地位。不同于其他容器如列表(List)或数组(Array),集合的主要特点是它存储的元素是唯一的,且这些元素默认按照某种规则进行排序(尽管在某些实现中,如C++的std::unordered_set,元素并不保证有序,但这里我们主要讨论的是有序集合)。这意味着在集合中,每个元素都只能出现一次,自动去除了重复项。

集合的每个元素都与一个键值(Key)相关联,在集合的上下文中,这个键值实际上就等于元素本身的值。这种键值合一的特性使得集合特别适合于需要快速判断某个元素是否存在,或者需要快速去除重复元素的场景。

为了实现这些高效的操作,集合内部通常采用了一种高效的数据结构作为支撑,其中最常见的就是红黑树(Red-Black Tree)。红黑树是一种自平衡的二叉查找树,它通过旋转操作和重新着色来保持树的平衡,从而确保在最坏情况下,树的深度仍然是对数级别的。这种性质使得集合的插入、删除和查找操作的时间复杂度都能保持在O(log n),其中n是集合中元素的数量。

红黑树的特性确保了集合操作的高效性,同时也使得集合在处理大规模数据集时依然能够保持出色的性能。无论是添加新元素时自动去重,还是快速查找某个元素是否存在,集合都能提供直观且高效的解决方案。

此外,集合还支持一些基本的集合操作,如并集(Union)、交集(Intersection)、差集(Difference)和对称差集(Symmetric Difference)等,这些操作使得集合在解决特定问题时更加灵活和强大。

2.2、集合的基本操作

 (1)创建集合

集合的创建非常简单,你只需包含 <set> 头文件,并定义一个集合类型即可。集合默认按照元素的自然排序规则进行排序,也可以自定义排序规则。

#include <iostream>
#include <set>
using namespace std;int main() {set<int> my_set; // 创建一个空的整数集合// 或者使用初始化列表创建集合set<int> another_set = {5, 3, 1, 4, 2};// 创建一个自定义排序规则的集合(例如按相反顺序排序)set<int, greater<int>> descending_set = {5, 3, 1, 4, 2};return 0;
}

 (2)插入元素

集合中的元素插入通常使用 insert 函数。由于集合不允许重复元素,所以尝试插入重复元素时,insert 操作将不会有任何效果。

#include <iostream>
#include <set>
using namespace std;int main() {set<int> my_set;// 插入元素my_set.insert(3);my_set.insert(1);my_set.insert(2);my_set.insert(1); // 尝试插入重复元素,但不会生效// 输出集合中的元素for (const auto& elem : my_set) {cout << elem << ' ';}cout << endl;// 插入提示和返回值auto result = my_set.insert(4);if (result.second) {cout << "Element inserted successfully." << endl;} else {cout << "Element already exists in the set." << endl;}return 0;
}

insert 函数的返回值是一个 pair 对象,其中包含一个指向新插入元素的迭代器和一个布尔值,指示插入是否成功。如果元素已经被插入,则返回的布尔值为 false

 (3) 访问元素

由于集合中的元素是有序的,你可以使用迭代器或 find, begin, end, rbegin, rend 等成员函数来访问元素。

A、使用迭代器访问元素
// 遍历并输出所有元素
for (auto it = my_set.begin(); it != my_set.end(); ++it) {cout << *it << ' ';
}
cout << endl;
B、使用 find 函数访问特定元素
auto it = my_set.find(3);
if (it != my_set.end()) {cout << "Found element: " << *it << endl;
} else {cout << "Element not found." << endl;
}
C、访问集合的首尾元素

集合没有直接的 frontback 函数来访问首尾元素,但可以通过迭代器实现类似功能:

cout << "First element: " << *my_set.begin() << endl;
cout << "Last element: " << *my_set.rbegin() << endl; // 注意,rbegin 返回逆序集合的开始迭代器

2.3、 其他集合操作

除了上述基本操作外,集合还提供了许多其他实用的操作,如 erase, swap, clear, empty 等,用于删除元素、交换集合内容、清空集合和检查集合是否为空。v

三、STL 容器之多重集合

3.1、什么是多重集合?

多重集合与集合相似,但是它允许存储重复的元素。这意味着在一个多重集合中,相同的键值可以出现多次。这在需要记录重复数据的场景中非常有用。

多重集合的操作与集合基本相同,只是在插入和查找重复元素时有一些细微差别。

3.2、集合与多重集合的高级操作

(1)查找元素

集合和多重集合提供了 findcount 方法来查找元素:

if (my_set.count(5) > 0) {// 元素存在
}

(2)范围操作

使用 lower_boundupper_bound 可以找到给定键值范围内的第一个和最后一个元素:

auto lower = my_set.lower_bound(3);
auto upper = my_set.upper_bound(5);

(3)迭代器操作

集合和多重集合的迭代器提供了对元素的访问和遍历能力:

for (const auto& elem : my_set) {cout << elem << ' ';
}

3.3、集合与多重集合的比较

集合和多重集合在功能上相似,但主要区别在于重复元素的处理:

集合

不允许重复元素,每个元素都是唯一的。
多重集合允许重复元素,可以存储多个相同键值的元素。

3.4、性能考量

集合和多重集合基于红黑树实现,这使得它们在插入、删除和查找操作上都表现出较高的效率。然而,由于它们维护元素的排序,所以在某些情况下,如需要频繁插入和删除元素时,可能不如其他容器如向量(vector)或列表(list)那样快。


以上就是 C++ 标准模板库中的集合(set)和多重集合(multiset)的基础知识点了。它们为开发者提供了高效的有序数据存储和检索能力。无论是处理需要排序的元素集合,还是需要统计重复数据的场景,集合和多重集合都能胜任。基本上在开发中都会用到的,大家多看看,一定要掌握。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

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

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

相关文章

刚刚 威尼斯影评人周公布 2024 年电影阵容 包括敏感纪录片《本土》

《本土》 威尼斯影评人周是威尼斯电影节专门为首次拍摄电影的人设立的侧边活动&#xff0c;该活动公布了第 39 届威尼斯电影节的七部竞赛片和两部非竞赛片的入选名单&#xff0c;第 39 届威尼斯电影节将于 8 月 28 日至 9 月 7 日举行。 较为及时的作品之一是美国导演迈克尔普…

【IntelliJ IDEA】一篇文章集合所有IDEA的所有设置

IntelliJ IDEA 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;其设置涵盖了多个方面&#xff0c;以满足不同开发者的需求和偏好。由于 IDEA 的设置相当复杂和详尽&#xff0c;这里无法在一篇简短的文章中详细介绍所有设置。然而&#xff0c;我可以提供一…

@SpringBootApplication 注解及源码 详解

SpringBootApplication(scanBasePackages {"com.XXX"}) 标注 启动类注解。 内含源码注解 Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Inherited SpringBootConfiguration EnableAutoConfiguration ComponentScan(excludeFilters …

CSS 计数器:WebKit 的样式增强术

CSS 计数器&#xff1a;WebKit 的样式增强术 CSS 计数器是 CSS2.1 规范中引入的一个强大特性&#xff0c;它允许网页开发者在文档中创建和维护计数器。这些计数器可以用于列表编号、章节编号、图表索引等场景。WebKit 引擎&#xff0c;作为许多流行浏览器&#xff08;如 Safar…

持续集成07--Jenkins配置Allure测试报告

前言 在持续集成&#xff08;CI&#xff09;流程中&#xff0c;自动化测试报告是评估软件质量和追踪问题的重要工具。Allure Framework作为一个轻量级且功能丰富的测试报告工具&#xff0c;能够生成详细的测试报告&#xff0c;帮助团队更好地理解测试结果。本章节“持续集成07-…

Java二十三种设计模式-装饰器模式(7/23)

装饰器模式&#xff1a;动态扩展功能的灵活之选 引言 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;用于在不修改对象自身的基础上&#xff0c;通过添加额外的职责来扩展对象的功能。 基础知识&#xff0c;java设计模式总体来说设计…

特征工程方法总结

方法有以下这些 首先看数据有没有重复值、缺失值情况 离散&#xff1a;独热 连续变量&#xff1a;离散化&#xff08;也成为分箱&#xff09; 作用&#xff1a;1.消除异常值影响 2.引入非线性因素&#xff0c;提升模型表现能力 3.缺点是会损失一些信息 怎么分&#xff1a;…

爬取百度图片,想爬谁就爬谁

前言 既然是做爬虫&#xff0c;那么肯定就会有一些小心思&#xff0c;比如去获取一些自己喜欢的资料等。 去百度图片去抓取图片吧 打开百度图片网站&#xff0c;点击搜索xxx&#xff0c;打开后&#xff0c;滚动滚动条&#xff0c;发现滚动条越来越小&#xff0c;说明图片加载…

使用 node --inspect 命令调试js文件执行

深入理解 Node.js 的 --inspect 调试功能 引言 Node.js 是一个流行的 JavaScript 运行环境&#xff0c;它允许开发者在服务器端运行 JavaScript 代码。随着应用的复杂性增加&#xff0c;调试成为了开发过程中不可或缺的一部分。Node.js 提供了强大的调试工具&#xff0c;其中…

3D 渲染一个房屋需要多长时间?

3D 渲染一个房屋总共需要 6-10 个工作日&#xff0c;主要取决于项目的复杂性和最终 3D 渲染的质量&#xff0c;图像越逼真&#xff0c;效果图渲染所需时间就越长。 1.3D建模 创建 3D 模型是第一步&#xff0c;所需时间可能因项目的复杂程度而有很大差异。一个简单的住宅渲染可…

D3.高精度

1.分类情况 AB、A-B、A*a、A/b A和B指的是超大超长整数&#xff0c;长度<1e6; a的值<10000&#xff1b; 2.大整数的存储 int 变量肯定是存不了这么大的数的&#xff0c;做法是将大整数先存到string字符串&#xff0c;再使用字符串的访问方式&#xff0c;将每一位数存到…

单机游戏分享:波与月夜之青莲单机游戏下载,2D和风动作游戏

在《波与月夜之青莲》中穿越一个充满神话和传奇的神秘世界。这是款丰富多彩的手绘冒险游戏&#xff0c;灵感来自于日本的民间传说。 扮演波&#xff0c;一朵从天而降的天体花&#xff0c;在一道古老而神秘的仪式中扮演关键的角色&#xff0c;展开一段神秘的旅程。使用你的传说…

CCF GESP Python编程 一级认证真题 2024年6月

一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级&#xff0c;那他可以选择的认证语会有几 种&#xff1f;&#xff08; &#xff09; A.1 B.2 C.3 D.4 第 2 题 ENIAC于1…

一、C#概述

本文是网页版《C# 12.0 本质论》第一章解读。欲完整跟踪本系列文章&#xff0c;请关注并订阅我的Essential C# 12.0解读专栏。 前言 第一章的内容非常简单&#xff0c;毕竟仅仅是Introducing C#。不过正如《0.前言》所述&#xff0c;《C# 12.0本质论》本身就不是一本零基础的…

Spark SQL----CREATE TABLE

Spark SQL----CREATE TABLE 一、描述二、创建 DATASOURCE 表2.1 描述2.2 语法2.3 参数2.4 数据源交互2.5 例子 三、创建HIVEFORMAT表3.1 描述3.2 语法3.3 参数3.4 例子 四、CREATE TABLE LIKE4.1 描述4.2 语法4.3 参数4.4 例子 一、描述 CREATE TABLE语句用于在现有数据库中定…

保护Mojo模型:确保数据模型安全的策略

保护Mojo模型&#xff1a;确保数据模型安全的策略 在机器学习领域&#xff0c;模型的安全性是至关重要的&#xff0c;尤其是当模型被部署到生产环境中时。Mojo模型&#xff0c;作为H2O.ai提供的一种模型导出格式&#xff0c;需要特别注意保护以防止潜在的安全风险。本文将详细…

rv1126利用rkmedia、opencv、rockx……完成人脸识别

一、总体框架 视频采集、处理使用rkmedia&#xff1a;vi模块进行视频输入、rga模块进行视频处理 人脸识别&#xff1a;先获取rga输出码流&#xff0c;再调用rkmedia的模型对人脸进行推理&#xff08;线程1&#xff09; 打框框&#xff1a;opencv&#xff08;线程2&#xff0…

在交互式系统中,非剥夺是不是一个好的策略?为什么?

非剥夺方式:分派程序一旦把处理机分配给某进程后便让它一直运行下去,直到进程完成或发生某事件而阻塞时,才把处理机分配给另一个进程。 剥夺方式:当一个进程正在运行时,系统可以基于某种原则,剥夺已分配给它的处理机,将之分配给其它进程。剥夺原则有:优先权原则、短进程、优先…

Docker 容器中的 Docker Compose 简介

Docker Compose是什么 Docker Compose是一个用于定义和运行多个Docker容器的工具。它是Docker官方提供的开源项目&#xff0c;用于实现对Docker容器集群的快速编排。通过Compose&#xff0c;开发者可以使用YAML文件&#xff08;通常是docker-compose.yml文件&#xff09;来配置…

Golang | Leetcode Golang题解之第264题丑数II

题目&#xff1a; 题解&#xff1a; func nthUglyNumber(n int) int {dp : make([]int, n1)dp[1] 1p2, p3, p5 : 1, 1, 1for i : 2; i < n; i {x2, x3, x5 : dp[p2]*2, dp[p3]*3, dp[p5]*5dp[i] min(min(x2, x3), x5)if dp[i] x2 {p2}if dp[i] x3 {p3}if dp[i] x5 {p5…