set(关联性容器)

news2025/7/10 13:38:43

众所周知,不会set的人就不会c++(你自己编的吧!),到底什么是set呢?我们今天就来了解一下set的奥秘.

set是啥

set 作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set 中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set 中数元素的值不能直接被改变。与map 的使用方法大致都相同。这时你们就可能有疑问了,啥是map呢?我们抽时间会给大家讲的(反正不是下期)

set的定义 

set<类型> 对象名; 如:set<int> s;

添加元素

set<int> s;
s.insert(8);
s.insert(10);
s.insert(6);
s.insert(8); //重复元素不会插入

set遍历

set 的遍历也是使用迭代器进行遍历, 可以正序遍历也可以反序遍历。

正序遍历

set<int>s;
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++)
    cout<<*it<<endl;

反序遍历

set<int>::reverse_iterator it;
for(it=s.rbegin();it!=s.rend();it++)
    cout<<*it<<endl

容器与迭代器

vector ​​​,stack ​​,queue ​​,map ​​​,set ​​​ 都是STL提供的标准数据结构,他们共同的特点是都是容器,用来存储元素集合。为了统一他们的使用方法,STL提供了迭代器。

容器

容器迭代器功能解释
vector随机访问
deque随机访问双端队列,可以从前后 push,pop 元素
list双向链表
set/multiset双向multiset 是允许有重复元素的 set ,元素保持有序
map/multimap双向multimap 是允许有重复元素的map ,元素是pair 保持有序
stack不支持迭代器
queue不支持迭代器队列
priority_queue不支持迭代器优先队列,每次可以从栈顶取出当前最小
容器添加元素的效率删除元素的效率查找元素访问中间的元素
vector加在尾部 𝑂(1),加在中间 𝑂(𝑛)。𝑂(𝑛)𝑂(𝑛)𝑂(1)
list𝑂(1)𝑂(1)𝑂(𝑛)𝑂(𝑛)
stack只能加在栈顶 𝑂(1)只能删除栈顶 𝑂(1)无法查找无法访问
queue只能加在队尾 𝑂(1)只能删除队首 𝑂(1)无法查找无法访问
set/map𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑙𝑜𝑔(𝑛))𝑂(𝑛)更高效率的访问需要自己实现

迭代器

迭代器按照定义方式分成以下四种:

1.正向迭代器(最常用),定义方法如下:
容器类名::iterator 迭代器名;
map<int, double>::iterator itor;
2.常量正向迭代器,定义方法如下:
容器类名::const_iterator 迭代器名;
vector<bool>::const_iterator citor;
3.反向迭代器,定义方法如下:
容器类名::reverse_iterator 迭代器名;
set<bool>::reverse_iterator ritor;
4.常量反向迭代器,定义方法如下:
容器类名::const_reverse_iterator 迭代器名;
set<int>::const_reverse_iterator critor;
容器方法解释
begin()返回容器首个元素的地址
end() ​返回容器最后一个元素再下一个元素的地址
rbegin()返回容器最后一个元素的地址
rend()返回容器首个元素再前一个元素的地址
find(value) ​查找元素,如果找到返回迭代器位置,否则返回end() 的位置
erase(iterator)删除迭代器元素

为了更深入理解迭代器的使用,我们试着运行一下下面的程序:

#include <bits/stdc++.h>
using namespace std;
set<int> st;
set<int>::iterator itor;
int main(){ 
    for(int i=1;i<6;i++){
        st.insert(i);
        itor=st.find(3);
        cout<<i<<" find(3) = end() : ";
        if(itor==st.end())
            cout<<"Yes";
        else
            cout<<"No";
        cout<<" end 位置读取值"<<*st.end()<<endl;
    }
    return 0;
}
1 find(3) = end() : Yes end 位置读取值1
2 find(3) = end() : Yes end 位置读取值2
3 find(3) = end() : No end 位置读取值3
4 find(3) = end() : No end 位置读取值4
5 find(3) = end() : No end 位置读取值5

上面是程序运行的结果,当我们插入了元素3后,发现 𝑓𝑖𝑛𝑑(3)!=𝑠𝑡.𝑒𝑛𝑑(),因此我们知道 end() 给出的地址并不是最后一个元素的地址。

同时发现,虽然 end 对应的是容器最后一个元素再下一个元素的地址,但我们用 ∗st.end() ​ 去读取值的时候,返回的却是最后一个元素的值。

迭代器本身支持 ++​ 和 −−操作,但不能够写成 𝑖𝑡𝑜𝑟=𝑖𝑡𝑜𝑟+1 ​。 ++操作返回的是下一个地址,−− ​ 是上一个。

但迭代器不一定支持 +=操作,只有可以随机访问的迭代器(例如:vector ​ 的迭代器),支持此类操作。

常用操作

begin(),               //返回set容器的第一个元素
end(),                 //返回set容器的最后一个元素
clear(),               //删除set容器中的所有的元素
empty(),               //判断set容器是否为空
max_size(),            //返回set容器可能包含的元素最大个数
size(),                //返回当前set容器中的元素个数
rbegin(),              //返回的值和end()相同
rend(),                //返回的值和begin()相同
erase(iterator),       //删除定位器iterator指向的值
erase(first,second),   //删除定位器first和second之间的值
erase(key_value),      //删除键值key_value的值
find() ,              //返回给定值值得定位器,如果没找到则返回end()。
  
set中还有两个非常重要的函数,lower_bound()和upper_bound()。这两个函数都需要传入一个值。
lower_bound返回的是大于或等于被查询元素的第一个元素位置的迭代器,如果找不到,迭代器则为set.end() 
upper_bound返回值则是>给定val的最小指针(iterator)。
rbegin() 和 rend()为反向迭代器。

因为set ​​ 中的元素本身是有序的,因此 begin() ​​ 会直接返回集合中最小的元素的位置,而 end()−− ​ 返回的是集合中最大元素的位置。

既然set 本身支持模板(泛型编程),那么set 也可以用来保存我们自定义的一些数据类型。那么这些类型将会按照什么样的顺序来排列呢?

同排序函数相同,我们可以自行定义比较的方法,但具体使用同sort 略有不同,需要自己定义一个struct 来做具体类型的比较,同时要定义一个名为operator 的bool 类型函数,具体请看下面的代码。

#include <bits/stdc++.h>
using namespace std;
//自定义比较结构体
struct Cmp{
    bool operator()(int l,int r){ 
        return l%10>r%10;
    }
};
int main(){
    set<int,Cmp>s;
    for(int i=7;i<27;i++)
        s.insert(i);
    set<int>::iterator it;
    for(it=s.begin();it!=s.end();it++)
        cout<<*it<<endl;
    return 0;
}

 9 8 7 16 15 14 13 12 11 10

以上为程序运行结果,我们来解释一下为什么会出现这样的运行结果呢?

首先,我们自定义的比较类型中会将一个数模 10的结果进行比较,并将更大的排在前面。另外因为set 会去重,所以在插入17 时,会发现已经存在%10=7 的数了,因此插入数据失败。

尾声

今天咱们就讲到这里,下篇博文再见👋👋

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

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

相关文章

Nacos学习笔记 (5)Nacos整合SpringBoot流程

前提&#xff0c;先下载Nacos并启动 Nacos Server。 1. Nacos 融合 Spring Boot 为注册配置中心 实现&#xff1a; 通过 Nacos Server 和 nacos-config-spring-boot-starter 实现配置的动态变更&#xff1b;通过 Nacos Server 和 nacos-discovery-spring-boot-starter 实现服…

16、Mysql高级之锁问题

16、Mysql高级之锁问题 文章目录16、Mysql高级之锁问题1、锁概述2、锁分类3、Mysql 锁4、MyISAM 表锁4.1 如何加表锁5.2.2 读锁案例4.3、写锁案例4.4、结论4.5、查看锁的争用情况5、InnoDB 行锁5.1、行锁介绍5.2、背景知识5.3、InnoDB 的行锁模式5.4、案例准备工作5.5、行锁基本…

机器学习模型-BUPA liver disorders-探索饮酒与肝炎关系(论文,科研,医疗信息化诊断系统用)

肝炎是由细菌、病毒、寄生虫、酒精、药物、化学物质、自身免疫等多种致病因素引起的肝脏炎症的统称。儿童及成年人均可患病&#xff0c;病毒感染导致的病毒性肝炎较为常见。 过渡饮酒是肝炎重要因素 过渡饮酒会引发下述血检指标异常&#xff0c;暗示肝炎发生。 酒精相关性肝病…

使用Nordic的nrf52840实现蓝牙DFU过程

需要用到的软件&#xff1a; 交叉编译环境&#xff1a;gcc-arm-none-eabi MinGW&#xff1a;下载 Python&#xff1a;下载 micro-ecc源码&#xff1a;下载 nRFUtil&#xff1a;下载或者直接使用python的pip来安装 手机app&#xff1a;nRF Toolbox或者nRF Connect 安装 gcc-…

【爬虫】JS调试解决反爬问题系列3—sign破解

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

LabVIEW如何减少下一代测试系统中的硬件过时 1

LabVIEW如何减少下一代测试系统中的硬件过时 1 许多测试系统的问题是&#xff0c;整个系统运行的时间必须超过单个系统组件的支持时间。有时被测试的设备有几十年的有效使用寿命&#xff0c;而许多测试仪器已经过时&#xff0c;在5年或更短的时间后就不再支持了。其他时候&…

技能梳理32@电源防反接电路+光耦隔离电路+串口磁耦隔离电路

电源防反接电路 CN2是个防反接插座&#xff1b; F1是个自恢复保险丝&#xff1b; MB6S是个整流桥电路&#xff0c;主要是这个模块实现的防反接效果&#xff1b; SPX3819是个电平转换模块&#xff0c;封装挺小的&#xff1b;LDO-EN是用来控制SPX3819是否使能的&#xff1b; …

等保2.0参与医院网络安全管理的重要性

随着现代医院 IT 技术架构的演变、新兴技术的引入&#xff0c;来自医院内外部的各种安全风险不断出现&#xff0c;对医院网络安全提出了更多挑战&#xff0c;医院网络安全在技术层面和管理层面都亟待完善。为此&#xff0c;借鉴相关法律法规、行业标准等&#xff0c;提出提升现…

Web前端开发神器WebStorm v2022.3发布——支持新的CSS功能

WebStorm是一款JavaScript 开发工具。被广大中国JS开发者誉为"Web前端开发神器""最强大的HTML5编辑器""最智能的JavaSscript IDE"等。与IntelliJ IDEA同源&#xff0c;继承了IntelliJ IDEA强大的JS部分的功能。 WebStorm v2022.3官方正式版下载…

百度工程师教你玩转设计模式(装饰器模式)

作者 | 北极星小组 想要写好代码&#xff0c;设计模式&#xff08;Design Pattern&#xff09;是必不可少的基本功&#xff0c;设计模式是对面向对象设计&#xff08;Object Oriented Design&#xff09;中反复出现的一类问题的一种解决方案&#xff0c;本篇介绍装饰器模式&am…

(第一章)OpGL超级宝典学习:配置和超级宝典相同的工作环境

目录前言配套资源配置解压文件夹复制资源HOWTOBUILD什么是CMake什么是GLFW安装CMake开始构建build glfw生成debug和release的lib库build sample推送结语前言 最近发现学习好像到了一定的瓶颈&#xff0c;马上要到2023年了&#xff0c;想要在新的一年开始后对自己有一定的突破&a…

Kubernetes 实现自动扩容和自愈应用实践

Kubernetes 自动扩容和自愈 tags: 实践 文章目录Kubernetes 自动扩容和自愈1. 背景2. 准备3. kind 部署 kubernetes4.实践4.1 部署 deployment4.2 创建 Service4.3 创建 Ingress4.4 部署 Ingress-nginx4.5 K8s 实现自愈4.6 k8s 实现自动扩容5. 其他1. 背景 在生产非 kubernet…

java进阶—List

上节回顾 List 是一个有序的&#xff0c;允许重复的Collection&#xff0c;其下的子类主要有 ArrayList LinkedList,Vector(这个官方不推荐使用) 那么同为list的子类&#xff0c;ArrayList 跟 LinkedList 有什么区别呢&#xff1f; 这里就涉及到了list的底层两种实现方式&…

《计算机体系结构量化研究方法》第2章-存储器层次结构设计 2.1 引言

一、概述 1、存储器层次结构&#xff1a;层次由速度和容量各不相同的存储器组成。 2、存储器层次结构被分为几个级别——离处理器越近&#xff0c;容量越小速度越快。 3、包含性质&#xff1a;大多数情况下&#xff0c;低层级存储器中的数据是上一级存储器中数据的超集。比如…

基于RSA的数字签名设计与实现

信息安全课程的第二个实验&#xff0c;主要是用java、js&#xff0c;前端页面用的html写的。 页面成果展示&#xff1a; 基本公私钥生成 实验环境为win10系统&#xff0c;使用git命令行工具——git bash生成公私钥。生成私钥&#xff0c;密钥长度为1024bit并从私钥中提取公钥 …

如何在 Spring Boot 项目中开启 “热部署“

目录 1. 添加热部署框架支持 2. 设置当前项目 Settings 和新项目 Settings 开启项目自动编译 3. 开启运行中热部署 4. 使用 Debug 启动项目 (社区版 IDEA) 1. 添加热部署框架支持 在 pom.xml 中添加如下框架引用: <dependency><groupId>org.springframework.b…

vue3中常用的三种组件传值方式

比较大型的项目中经常会涉及到多个组件之间进行传值&#xff0c;所以对之前用过的一些传值方法做个笔记&#xff0c;还有就是对不同的情况下需要使用哪一种传值方法更合适的思维进行一个总结 vue3中常用的三种组件传值方式mitt依赖注入pinia总结mitt 因为vue3去掉了全局事件总…

qt实现的pdf阅读器(二)--XpdfReader在linux下的编译

目录 1.简介 2.需求说明 3.编译 3.3. 下载源码 3.2. 移植安装包和依赖库 3.2.1 准备工作 3.3.2 了解 3.3.3 编译并安装zlib 3.3.4 编译并安装libpng 3.3.5 编译并安装lcms 3.3.6 编译并安装freetype 3.3.7 编译xpdf 3.3.8 查看运行编译好的xpdf 1.简介 Xpdf 是一个免…

我以为自己MySQL够牛逼了,直到看到了Alibaba的面试题

前言 众所周知&#xff0c;简历上“了解&#xff1d;听过名字&#xff1b;熟悉&#xff1d;知道是啥&#xff1b;熟练&#xff1d;用过&#xff1b;精通&#xff1d;做过东西”。 相信大家对于MySQL的索引都不陌生&#xff0c;索引(Index)是帮助MySQL高效获取数据的数据结构。…

SpringBoot Disruptor框架遇到的问题

1.消息重复消费问题 问题描述&#xff1a; 项目中启动了多个消费者,测试中发现同一条消息被多次消费。 解决方案&#xff1a; ①幂等方案处理 ②disrutor提供了不同的处理机制&#xff1a; 自定义消费者实现EventHandler接口,他是属于重复消费&#xff0c; 自定义消费者实现W…