【C++】STL标准模板库容器set

🦄个人主页:修修修也

🎏所属专栏:C++

⚙️操作环境:Visual Studio 2022


目录

📌关联式容器set(集合)简介

📌set(集合)的使用

🎏set(集合)的模板参数列表

🎏set(集合)的构造函数

🎏set(集合)的迭代器

🎏set(集合)的容量

🎏set(集合)的修改操作

📌关联式容器multiset简介 

📌关联式容器multiset使用

结语


        在之前对STL的学习中,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,根据"数据在容器中的排列"特性,这些容器统称为序列式(sequence)容器,因为其底层为线性序列的数据结构,里面存储的是元素本身

        还有一种容器是关联式(associative)容器, 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

        下图列出了STL中的各种容器,以及其基层与衍生层的关系:


📌关联式容器set(集合)简介

        我们先来看一下cplusplus.com - The C++ Resources Network网站对set的文档介绍:

        总结一下:

  1. set是按照一定次序存储元素的容器。
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的。

        注意:

  • 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  • set中插入元素时,只需要插入value即可,不需要构造键值对。
  • set中的元素不可以重复(因此可以使用set进行去重)。
  • 使用set的迭代器遍历set中的元素,可以得到有序序列。
  • set中的元素默认按照小于来比较。
  • set中查找某个元素,时间复杂度为:$log_2 n$
  • set中的元素不允许修改(因为修改key可能会导致二叉搜索树结构被破坏)。
  • set中的底层使用二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))来实现。

📌set(集合)的使用

🎏set(集合)的模板参数列表

        set的模板参数及含义如下:


🎏set(集合)的构造函数

        set的构造函数及其功能如下:

        使用示例如下:

#include<iostream>
#include<vector>
#include<set>
using namespace std;int main()
{//构造一个没有元素的空容器set<int> s1;for (auto e : s1){cout << e << " ";}cout << endl;vector<int> v;v.push_back(2);v.push_back(5);v.push_back(1);v.push_back(4);v.push_back(3);//迭代器区间构造set<int> s2(v.begin(), v.end());for (auto e : s2){cout << e << " ";}cout << endl;//拷贝构造set<int> s3(s2);for (auto e : s3){cout << e << " ";}cout << endl;return 0;
}

        运行效果如下:


🎏set(集合)的迭代器

        set的迭代器相关函数及其功能如下:

        使用示例如下:

int main()
{vector<int> v;v.push_back(2);v.push_back(5);v.push_back(1);v.push_back(4);v.push_back(3);//迭代器区间构造set<int> s(v.begin(), v.end());//正向迭代器set<int>::iterator it_b = s.begin();	//访问正向迭代器开始cout << *it_b << endl;set<int>::iterator it_e = s.end();		//访问正向迭代器结束--it_e;									cout << *it_e << endl;++it_e;while (it_b != it_e){cout << *it_b << " ";			//使用正向迭代器遍历set++it_b;}cout << endl;//反向迭代器set<int>::reverse_iterator rit_b = s.rbegin();		//访问反向迭代器开始cout << *rit_b << endl;set<int>::reverse_iterator rit_e = s.rend();		//访问反向迭代器结束--rit_e;cout << *rit_e << endl;++rit_e;while (rit_b != rit_e){cout << *rit_b << " ";			//使用反向迭代器遍历set++rit_b;}cout << endl;return 0;
}

        运行结果如下:


🎏set(集合)的容量

        set的容量相关函数及其功能如下:

        使用示例如下:

int main()
{//构造一个没有元素的空容器set<int> s1;cout << s1.empty() << endl;cout << s1.size() << endl;cout << s1.max_size() << endl;vector<int> v;v.push_back(2);v.push_back(5);v.push_back(1);v.push_back(4);v.push_back(3);//迭代器区间构造set<int> s2(v.begin(), v.end());cout << s2.empty() << endl;cout << s2.size() << endl;cout << s2.max_size() << endl;return 0;
}

        运行结果如下:


🎏set(集合)的修改操作

        set的修改相关函数及其功能如下:

函数声明功能介绍
pair<iterator, bool> insert(const value_type&x)在set中插入元素x,实际插入的是<x, x>构成的
键值对,如果插入成功,返回<该元素在set中的
位置,true>,如果插入失败,说明x在set中已经
存在,返回<x在set中的位置,false>
void erase ( iterator position )

删除set中position位置上的元素

size_type erase ( const key_type& x )删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last )删除set中[first, last)区间中的元素
void swap ( set<Key,Compare,Allocator>& st )交换两个set中的元素
void clear ( )将set中的元素清空
iterator find ( const key_type& x ) const返回set中值为x的元素的位置
size_type count ( const key_type& x ) const返回set中值为x的元素的个数

        insert,erase,clear,find函数使用示例如下:

int main()
{//构造一个没有元素的空容器set<int> s1;//插入元素s1.insert(3);s1.insert(1);s1.insert(7);s1.insert(4);s1.insert(0);s1.insert(8);s1.insert(2);s1.insert(6);s1.insert(9);s1.insert(5);for (auto k : s1){cout << k << " ";}cout << endl;set<int>::iterator pos = s1.find(1);//迭代器删除元素s1.erase(pos);for (auto k : s1){cout << k << " ";}cout << endl;//key值删除元素s1.erase(3);for (auto k : s1){cout << k << " ";}cout << endl;//迭代区间删除元素s1.erase(s1.begin(), s1.find(5));for (auto k : s1){cout << k << " ";}cout << endl;//清空set中的元素s1.clear();for (auto k : s1){cout << k << " ";}cout << endl;return 0;
}

        运行结果如下:

        swap函数使用示例如下:

int main()
{//构造两个没有元素的空容器set<int> s1;set<int> s2;//s1中插入元素s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(0);s1.insert(2);cout << "s1 : ";for (auto k : s1){cout << k << " ";}cout << endl;cout << "s2 : ";for (auto k : s2){cout << k << " ";}cout << endl;//交换s1和s2的值s1.swap(s2);cout << "s1 : ";for (auto k : s1){cout << k << " ";}cout << endl;cout << "s2 : ";for (auto k : s2){cout << k << " ";}cout << endl;return 0;
}

        运行结果如下:

        count()函数的定义如下图: 

      

        count函数使用示例如下:

int main()
{//构造一个没有元素的空容器set<int> s1;//s1中插入元素s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(0);s1.insert(2);cout << "s1 : ";for (auto k : s1){cout << k << " ";}cout << endl;cout << s1.count(2) << endl;cout << s1.count(4) << endl;cout << s1.count(6) << endl;cout << s1.count(8) << endl;return 0;
}

        运行结果如下:


📌关联式容器multiset简介 

         我们先来看一下cplusplus.com - The C++ Resources Network网站对set的文档介绍:

        总结一下:

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。
  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。
  5. multiset底层结构为二叉搜索树(红黑树)

        注意:

  1. multiset中再底层中存储的是<value, value>的键值对
  2. mtltiset的插入接口中只需要插入即可
  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的
  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
  5. multiset中的元素不能修改
  6. 在multiset中找某个元素,时间复杂度为$O(log_2 N)$
  7. multiset的作用:可以对元素进行排序

📌关联式容器multiset使用

        multiset的接口是和set一模一样的,区别在于具体的使用上:

        首先,multiset支持插入重复的键值key, 这就意味着multiset没有set的去重作用 :

int main()
{//构造一个没有元素的空容器setset<int> s;s.insert(3);s.insert(1);s.insert(5);s.insert(5);	//插入多个重复键值keys.insert(5);s.insert(4);s.insert(5);s.insert(2);for (auto e : s){cout << e << " ";}cout << endl;//构造一个没有元素的空容器multisetmultiset<int> ms;ms.insert(3);ms.insert(1);ms.insert(5);ms.insert(5);	//插入多个重复键值keyms.insert(5);ms.insert(4);ms.insert(5);ms.insert(2);for (auto e : ms){cout << e << " ";}cout << endl;return 0;
}

        运行结果如下:

        同时,对于set模板里几乎没有什么意义的几个函数接口在multiset这里就可以得到很好的应用了,如:count,equal_range等函数:

        如下代码,我们利用count函数计算multiset中5出现的次数,并利用equal_range函数将其全部删除:

int main()
{//构造一个没有元素的空容器multisetmultiset<int> ms;ms.insert(3);ms.insert(1);ms.insert(5);ms.insert(5);	//插入多个重复键值keyms.insert(5);ms.insert(4);ms.insert(5);ms.insert(2);for (auto e : ms){cout << e << " ";}cout << endl;//计算5出现的次数cout << "5出现的次数: " << ms.count(5) << endl;//删掉所有的5pair<multiset<int>::iterator, multiset<int>::iterator> ret = ms.equal_range(5);	//这里ret的类型直接用auto也行multiset<int>::iterator left = ret.first;multiset<int>::iterator right = ret.second;ms.erase(left, right);for (auto e : ms){cout << e << " ";}cout << endl;return 0;
}

        运行结果如下:


结语

希望这篇关于 STL标准模板库容器set 的博客能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++】模拟实现二叉搜索(排序)树

【数据结构】C语言实现链式二叉树(附完整运行代码)

【数据结构】什么是二叉搜索(排序)树?

【C++】模拟实现priority_queue(优先级队列)

【C++】模拟实现queue

【C++】模拟实现stack

【C++】模拟实现list

【C++】模拟实现vector

【C++】标准库类型vector

【C++】模拟实现string类

【C++】标准库类型string

【C++】构建第一个C++类:Date类

【C++】类的六大默认成员函数及其特性(万字详解)

【C++】什么是类与对象?


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

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

相关文章

Vue 项目实战4-无缝轮播图

养成好习惯&#xff0c;先赞后看&#xff0c;感谢对作者大大的支持 一、话不多说&#xff0c;直接上效果图&#xff1a; 完整视频展示链接如下&#xff1a; https://item.taobao.com/item.htm?ftt&id833405684191 二、实现思路 HTML结构 文档头部设置&#xff1a;定义…

GEE教程:利用NASA的SMAP(Soil Moisture Active Passive)数据计算2020-2024年的时序土壤湿度分析

目录 数据 函数 paint(featureCollection, color, width) Arguments: Returns: Image ui.Chart.image.seriesByRegion(imageCollection, regions, reducer, band, scale, xProperty, seriesProperty) Arguments: 代码 结果 数据 SPL3SMP_E/005是NASA的SMAP(Soil Moi…

C# 委托(Delegate)二

一.委托的多播&#xff08;Multicasting of a Delegate&#xff09;&#xff1a; 委托对象&#xff0c;使用 "" 运算符进行合并&#xff0c;一个合并委托调用它所合并的两个委托。使用"-" 运算符从合并的委托中移除组件委托。 注&#xff1a;只有相同类型…

C语言编译和链接详解(通俗易懂,深入本质)

我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有.exe和.com(其中.exe比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判…

小小扑克牌算法

1.定义一个扑克牌类Card&#xff1a; package democard; public class Card {public String suit;//表示花色public int rank;//表示牌点数Overridepublic String toString() {return "{"suit rank"}";}//实例方法&#xff0c;初始化牌的点数和花色public…

Redis篇(初识Redis)

目录 一、数据库 二、NoSQL 三、认识Redis 三、关系数据库与非关系数据库对比 1. 结构化与非结构化 2. 关联和非关联 3. 查询方式 4. 事务 5. 存储方式 6. 扩展性 7. 总结 7.1. 图形梳理 7.2. 表格梳理 7.3. 优缺点 关系型数据库 非关系型数据库 四、再次认识R…

centos7官方源失效后的解决方案

自从官方源不再维护后&#xff0c;安装centos7&#xff0c;遇到了升级GCC问题。 以前什么都不需要配置&#xff0c;只需要以下命令就能安装和使用对应的GCC版本。 yum install centos-release-scl yum install scl-utils # 查询软件集合 yum list all --enablerepocentos-sc…

word中的表格全部设置宽度100%

1、背景 我们用工具将数据库或其他的数据导出成word时&#xff0c;表格有的会大于100%&#xff0c;超过了边界。word没有提供全局修改的方法。如果我们想改成100%。 一种方式是通过宏&#xff0c;全局改。一种是手动改。 2、宏修改 如果表格多&#xff0c;可以通过这种方式。…

【前端面试题】Vue 3 生命周期钩子的执行顺序详解

前言 在 Vue 3 中&#xff0c;生命周期钩子的执行顺序与 Vue 2 有所不同&#xff0c;特别是 setup 函数取代了传统的生命周期钩子 beforeCreate 和 created。本文将详细解析 Vue 3 的生命周期钩子执行顺序&#xff0c;帮助你更好地理解 Vue 3 的组件生命周期及其工作机制。 V…

【Qt】前后端交互---DataCenter类

设计目的 前后端交互系统中&#xff0c;创建并使用数据核心类的目的就是让该类作为客户端的数据中心&#xff0c;也就是说其负责管理客户端的所有数据与服务器的网络通信。 数据持久化 初始化数据文件 该函数设计的目的就是用于检查所需要的文件和目录是否存在&#xff0c;如…

You are not allowed to push code to this project

原因1 用户权限不够。 具体查看用户权限路径&#xff1a; 原因2 vscode之前都能提交代码&#xff0c;但是突然就提交不上了。 表现为:前端代码能拉取&#xff0c;但是不能提交。使用idea进行前端代码的提交&#xff0c;完全没问题。 解决方案&#xff1a;修改TortoiseG…

新160个crackme - 066-Andrnalin.3

运行分析 文字是德语&#xff0c;需要破解Key PE分析 VB程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 使用 VB Decompiler 静态分析&#xff0c;发现逻辑如下&#xff1a;1、提取Key每个字符 102、计算后的Key要与"kXy^rO|yXom\kMuOn*"相等 算法分析…

0基础学前端 day4

大家好&#xff0c;欢迎来到无限大的频道。 今天继续带领大家开始0基础学前端。 一、 什么是Bootstrap框架&#xff1f; Bootstrap是一个开源前端框架&#xff0c;于2011年由Twitter的开发团队开发并发布。其主要目的是简化开发过程&#xff0c;并使开发者能够轻松快速地构建…

25 基于51单片机的温度电流电压检测系统(压力、电压、温度、电流、LCD1602)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;通过DS18B20检测温度&#xff0c;滑动变阻器连接数模转换器模拟电流、电压&#xff0c;通过LCD1602显示&#xff0c;程序里设置温度阈值为40&#xff0c;电流阈值为60&am…

[大语言模型-论文精读] 以《黑神话:悟空》为研究案例探讨VLMs能否玩动作角色扮演游戏?

1. 论文简介 论文《Can VLMs Play Action Role-Playing Games? Take Black Myth Wukong as a Study Case》是阿里巴巴集团的Peng Chen、Pi Bu、Jun Song和Yuan Gao&#xff0c;在2024.09.19提交到arXiv上的研究论文。 论文: https://arxiv.org/abs/2409.12889代码和数据: h…

openKylin--安装 .net6.0

编辑profile文件 cd .. //切换到根目录 cd /etc //切换到etc目录 vim profile //b编辑profile文件 1. 按→键移动到文件末尾 2. 按Insert键进入编辑模式 3. 按Enter另起一行开始编辑 export DOTNET_ROOT/home/dotnetexport PATH$PATH:/home/dotnet 可以通过右键--粘贴 的…

【Rust练习】16.方法和关联函数

练习题来自&#xff1a;https://practice-zh.course.rs/method.html 1 &#x1f31f;&#x1f31f; 方法跟函数类似&#xff1a;都是使用 fn 声明&#xff0c;有参数和返回值。但是与函数不同的是&#xff0c;方法定义在结构体的上下文中(枚举、特征对象也可以定义方法)&#…

使用Crawler实例进行网页内容抓取

网页内容抓取的背景 随着互联网的快速发展&#xff0c;网页上的信息量日益庞大。如何从海量的网页中快速、准确地抓取所需信息&#xff0c;成为了一个技术挑战。网页内容抓取技术通过自动化的方式&#xff0c;模拟用户浏览网页的过程&#xff0c;获取网页上的文本、图片、链接…

简介图片生成大模型imagen

Imagen 是谷歌提出的一种基于文本描述生成高质量图像的大规模深度学习模型&#xff0c;其核心概念类似于DALLE等生成模型&#xff0c;但在架构和生成效果上做了创新。它通过结合大型语言模型&#xff08;例如 T5&#xff09;和扩散模型&#xff08;diffusion models&#xff09…

通信工程学习:什么是FDD频分双工

FDD:频分双工 FDD(频分双工,Frequency Division Duplexing)是一种无线通信技术,它通过将频谱划分为上行和下行两个不重叠的频段来实现同时双向通信。以下是FDD频分双工的详细解释: 一、定义与原理 定义: FDD是一种无线通信系统的工作模式,其中上行链路(从移动…