【C++历险记】STL之set详解

个人主页:兜里有颗棉花糖💪
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【C++之路】💌
本专栏旨在记录C++的学习路线,望对大家有所帮助🙇‍
希望我们一起努力、成长,共同进步。🍓
在这里插入图片描述

目录

  • set
    • Modifiers
      • insert(插入数据)
      • erase(删除元素)
    • Operations:
      • find(查找数据)
      • count
        • find函数和count函数的区别
      • lower_bound & upper_bound
    • 补充(multiset)
      • equal_range

set

集合(Set):是一种不允许重复元素的容器,它的元素是按照某种特定顺序组织的。

头文件:

  • #include<set>

迭代器访问:

// 方式1:
set<int>::iterator it = s.begin();
while (it != s.end())
{cout << *it << ' ';it++;
}
// 方式2
for (auto e : s)cout << e << ' ';
// 方式3
for (set<int>::iterator it1 = s.begin(); it1 != s.end(); it1++)cout << *it1 << ' ';
// 其实这里方式1和方式3是等同的

Modifiers

insert(插入数据)

void test_set1()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(4);s.insert(4);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << ' ';it++;}cout << endl;
}

运行结果如下:
在这里插入图片描述
可以看到结果中并没有打印两个4,因为set容器会对其中的元素进行去重操作。

erase(删除元素)

void test_set2()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(4);s.insert(4);set<int>::iterator it = s.begin();for (auto e : s)cout << e << ' ';cout << endl;// 删除元素方式1auto pos = s.find(3);s.erase(pos);//s.erase(3); // 删除元素方式2for (auto e : s)cout << e << ' ';cout << endl;
}

运行结果如下:
在这里插入图片描述

上面提供了两种删除元素的方式,我们要根据不同的场景来选择不同的方式来进行删除元素。

Operations:

find(查找数据)

set的find函数用于在set中查找指定的元素,如果找到了,它返回指向该元素的迭代器;如果没有找到,返回一个指向set末尾元素的迭代器
在这里插入图片描述

请看举例:

void test_set3()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(4);s.insert(4);auto pos1 = s.find(5);auto pos2 = s.find(4);if (pos1 != s.end())s.erase(pos1);elsecout << "没找到该元素" << endl;if (pos2 != s.end())s.erase(pos2);for (auto e : s)cout << e << ' ';
}

运行结果如下:

在这里插入图片描述
需要注意的是,set的find函数和库中的find函数是不同的函数。

区别主要是查找速度上,set的find函数查找元素的时间复杂度是O(logN)

而库中的find函数查找的速度是O(N)

所以日常当中如果我们需要使用set中的find函数来查找元素时,我们可以这样使用,请看:

set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(4);
if (s.find(4) != s.end())cout << "该元素已被找到" << endl;
elsecout << "未找到该元素" << endl;

count

在这里插入图片描述
如果该元素存在的话则返回1,否则返回0。

这里只举一个简单的例子即可,请看:

set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(4);
if (s.count(4))cout << "集合中存在该元素" << endl;
elsecout << "集合中不存在该元素" << endl;

运行结果如下:
在这里插入图片描述

find函数和count函数的区别

set的find函数和count函数都是用来查找集合元素的函数,但要说区别的话还是有的。

返回值:find函数返回一个指向集合元素的迭代器,如果集合中不存在该元素,则迭代器指向集合的末尾;而count函数则返回集合中值等于给定值的元素数量,因为集合中元素是唯一的,所以返回值只能是0或1。

时间复杂度:count函数的时间复杂度要比find函数快,因为count函数只需要确定是否存在该元素,而不必遍历整个集合。

如果只需要知道一个元素是否存在于集合中,可以使用count函数;如果需要获取该元素的迭代器,或者对集合进行修改、删除、插入等操作,就需要使用find函数。

lower_bound & upper_bound

lower_bound函数用于查找大于或等于指定元素的第一个元素的迭代器如果找到指定元素,则返回指向该元素的迭代器,否则返回指向set末尾(即end)的迭代器。

upper_bound函数用于查找大于指定元素的第一个元素的迭代器;如果没有找到则返回指向set末尾(即end)的迭代器。

请看举例:

void test_set5()
{set<int> s;for (int i = 1; i <= 10; i++) s.insert(i * 10); // 10 20 30 40 50 60 70 80 90 100set<int>::iterator itlow, itup;itlow = s.lower_bound(30), itup = s.upper_bound(60);cout << *itlow << ' ' << *itup << endl;s.erase(itlow, itup);for (auto e : s) cout << e << ' ';cout << endl;
}

运行结果如下:
在这里插入图片描述

这里我们需要注意的是,erase函数删除的范围是左闭右开的,即实际删除的元素包括第一个迭代器指向的元素,但不包括第二个迭代器指向的元素。
同时这里要再次强调lower_bound函数查找的是大于或等于指定元素的第一个元素的迭代器,而upper_bound用于查找大于指定元素的第一个元素的迭代器。

补充(multiset)

这里要补充一点,在C++中setmultiset是C++标准库中的两个关联容器,二者的唯一区别在于容器中的元素是否唯一

这里举一个简单的例子即可,请看:

void test_set6()
{multiset<int> s;s.insert(1);s.insert(2);s.insert(4);s.insert(5);s.insert(5);s.insert(5);s.insert(3);s.insert(6);for (auto e : s) cout << e << ' ';cout << endl;cout << "容器中元素5的个数是:" << s.count(5) << endl;auto ret = s.equal_range(5);auto itlow = ret.first;auto itup = ret.second;s.erase(itlow, itup);for (auto e : s) cout << e << ' ';cout << endl;
}

运行结果如下:
在这里插入图片描述

这里我们要注意的是,如果multiset容器中有多个元素5,那么,如果使用find函数来查找元素5的话,此时应该返回的是中序的第一个元素5。请看举例:

multiset<int> s;
s.insert(1);
s.insert(2);
s.insert(4);
s.insert(5);
s.insert(5);
s.insert(5);
s.insert(3);
s.insert(6);
for (auto e : s) cout << e << ' ';
cout << endl;
auto pos = s.find(5);
while (pos != s.end())
{cout << *pos << ' ';pos++;
}
cout << endl;

运行结果如下:
在这里插入图片描述

equal_range

我们其实可以认为count函数和equal_range函数就是专门为multiset容器设计的。因为set容器中不存在相等的值,而multiset容器才存在相等的值。

下面我们来看一下multiset容器是如何使用equal_range函数的。

方式1:

void test_multiset1()
{multiset<int> s;s.insert(1);s.insert(2);s.insert(4);s.insert(5);s.insert(5);s.insert(5);s.insert(3);s.insert(6);for (auto e : s) cout << e << ' ';cout << endl;auto ret = s.equal_range(5);auto itlow = ret.first;auto itup = ret.second;s.erase(itlow, itup);for (auto e : s) cout << e << ' ';cout << endl;
}

在这里插入图片描述

方式2:
在这里插入图片描述
这里注意itlow和itup迭代器指向的值。

错误演示1:
在这里插入图片描述

这里equal_range返回的是一个不存在的区间。所以最终肯定会报错。

错误演示2:

在这里插入图片描述
这里出错点就在于返回给itup的值是一个不合法的值,所以*itup的时候就会报错。

以上就是对set容器用法的介绍,本文就到这里吧,再见啦友友们!!!

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

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

相关文章

GitHub Universe 2023:AI 技术引领软件开发创新浪潮

GitHub 是全球领先的软件开发和协作平台&#xff0c;数百万开发者和企业在此分享、学习和创建卓越的软件。同时 GitHub 处在 AI 技术前沿&#xff0c;通过其先进的 AI 技术增强开发者体验并赋能未来软件开发的使命。在今天的文章中&#xff0c;我们将一起看看在 GitHub 年度大会…

数据结构和算法八股与手撕

数据结构和算法八股文 第一章 数据结构 1.1 常见结构 见http://t.csdnimg.cn/gmc3U 1.2 二叉树重点 1.2.1 各种树的定义 满二叉树&#xff1a;只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上 完全二叉树&#xff1a;除了最底层节点可能没填满外&…

MCU通过KT6368A用SPP透传发送1K左右的数据,手机APP显示是3个包或者4个包,但是我看手册说最大一个包是512,理论应该是两个包吧,请问这正常吗?

一、问题简介 MCU通过KT6368A用SPP透传发送1K左右的数据&#xff0c;手机APP显示是3个包或者4个包&#xff0c;但是我看手册说最大一个包是512&#xff0c;理论应该是两个包吧&#xff0c;请问这正常吗&#xff1f; 详细说明 实际测试的截图如下&#xff1a;使用的是安卓app…

Windows电脑训练 RT-DETR 改进算法 (Ultralytics) 教程,改进RTDETR算法(包括使用训练、验证、推理教程)

手把手从零开始训练 RT-DETR 改进项目 (Ultralytics版本) 教程,改进RTDETR算法 本文以Windows服务器为例:从零开始使用Windows训练 RT-DETR 算法项目 《芒果剑指 RT-DETR 目标检测算法 改进》 适用于芒果专栏改进RT-DETR算法 文章目录 百度 RT-DETR 算法介绍改进网络代码汇…

【数据结构】树与二叉树(十四):二叉树的基础操作:查找给定结点的父亲(算法Father )

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

动手学深度学习——文本预处理

文本预处理 1. 读取数据集2. 词元化3. 词表4. 整合所有功能5. 小结 将文本作为字符串加载到内存中。 将字符串拆分为词元&#xff08;如单词和字符&#xff09;。 建立一个词表&#xff0c;将拆分的词元映射到数字索引。 将文本转换为数字索引序列&#xff0c;方便模型操作。…

7-爬虫-中间件和下载中间件(加代理,加请求头,加cookie)、scrapy集成selenium、源码去重规则(布隆过滤器)、分布式爬虫

0 持久化(pipelines.py)使用步骤 1 爬虫中间件和下载中间件 1.1 爬虫中间件(一般不用) 1.2 下载中间件&#xff08;代理&#xff0c;加请求头&#xff0c;加cookie&#xff09; 1.2.1 加请求头(加到请求对象中) 1.2.2 加cookie 1.2.3 加代理 2 scrapy集成selenium 3 源码去重…

如何使用Servlet写一个简单的网站

文章目录 前言1. 创建项目2. 引入依赖3. 创建目录4. 编写代码5. 打包程序6. 部署7.验证程序将 tomcat 集成到 idea 中 前言 前面我们学习了Java中常用的 HTTP 服务器 tomcat 的安装和使用&#xff0c;那么今天我们将使用这个 HTTP 服务器为大家写一个简单的网站&#xff0c;这…

关于跨域问题的个人理解

我也工作蛮多年了&#xff0c;期间既做过前端也做过后端。对于跨域问题&#xff0c;究竟是由前端程序员还是后端程序员来解决&#xff0c;我在不同的时期有不同的理解。现在&#xff0c;我更倾向于认为跨域问题应该由前端程序员来解决&#xff0c;即使在解决跨域问题的过程中涉…

【Python3】【力扣题】268. 丢失的数字

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;哈希。元素去重&#xff0c;依次判断是否在0-n内&#xff0c;没有则返回。 知识点&#xff1a;set(...)&#xff1a;转为集合&#xff0c;集合中的元素不重复。 class Solution:def mis…

【Spring Boot】034-Spring Boot 整合 JUnit

【Spring Boot】034-Spring Boot 整合 JUnit 文章目录 【Spring Boot】034-Spring Boot 整合 JUnit一、单元测试1、什么是单元2、什么是单元测试3、为什么要单元测试 二、JUnit1、概述简介特点 2、JUnit4概述基本用法 3、JUnit5概述组成 4、JUnit5 与 JUnit4 的常用注解对比 三…

【SpringBoot3+Vue3】二【实战篇】-后端

目录 一、环境搭建 1、数据库脚本 2、pom 3、yml 4、通过mybatis-X生成实体pojo等 4.1 Article 4.2 Category 4.3 User 5、 Mapper 5.1 ArticleMapper 5.2 CategoryMapper 5.3 UserMapper 6、service 6.1 ArticleService 6.2 CategoryService 6.3 UserService …