STL常用容器—set容器

news2024/9/24 9:27:29

STL常用容器—set容器

  • 1. set容器相关概念
  • 2. 初始化容器
  • 3. set容器插入和删除
  • 4. set容器大小和交换
  • 5. set容器的查找和统计
  • 6. set、multiset、unordered_set三者的区别
  • 7. pair对组的创建
  • 8. set容器的排序

参考博文:STL常用容器——set容器的使用

1. set容器相关概念

set容器特点:

  • 所有元素插入时候会被自动排序
  • set容器不允许插入重复值
  • 出入数据 只能用insert

set容器本质:
  set/multiset属于关联式容器,底层结构是用二叉树实现

2. 初始化容器

定义与初始化

默认构造: 
	set<int> s1;	
构造容器并初始化:
	set<int> s2{1,2,3,5,4};
拷贝构造:
	set<int> s3(s2);	
//等同于赋值
set<int> s3 = s2;	

插入数据

set容器插入数据只能使用insert

set<int> s2{1,2,3,5,4};
s2.insert(15);	//s2容器中插入数据15
s2.insert(10);	//s2容器中插入数据10
s2.insert(15);	//s2容器中插入数据15
show_set(s2);

若插入已存在的数据,插入失败但不报错,因为set容器数据不能重复

输出结果:

1 2 3 5 4 5 10 15
在这里插入图片描述

打印输出
注: 打印输出容器函数,后续打印没有特别说明均使用的是该函数

void show_set(set<int> &s)
{
	for(set<int>::iterator it = s.begin(); it != s.end();it++)
		cout << *it << " ";
	cout << endl;
}

3. set容器插入和删除

方法功能
☆ insert( elem )在容器中插入元素,常用
clear( )清空容器(删除所有元素)
erase( pos )删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end)删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
☆ erase(elem)删除容器中值为elem的元素
void test03()
{
	set<int> s1{2,5,3,8,0,3,6};		//构造容器并初始化
	//容器实际排序 0 2 3 5 6 8
	
	//删除某个元素
	s1.erase(100);	//若该元素不存在,则容器不变
	
	//删除某个迭代位置 删除第一个
	s1.erase(s1.begin());	// 2 3 5 6 8
	//删除最后一个
	s1.erase(--s1.end());	
	show_set(s1);			// 2 3 5 6
	
	//删除某个迭代区间
	s1.erase(++s1.begin(), --s1.end());	
	show_set(s1);			// 2 6
	
	s1.clear();		//清空容器
}

4. set容器大小和交换

方法功能
size();返回容器中元素的数目
empty( );判断容器是否为空
swap( st );交换两个集合容器
void test04()
{
	set<int> s1{10,20,45,30};	//默认构造 
	set<int> s2{1,2,3,5,4};		//构造容器并初始化
	
	//判断容器是否为空
	if(!s1.empty()){
		//若不为空 则输出容器的大小
		cout << "s1.size= " << s1.size() << endl;
		cout << "s1: ";
		show_set(s1);	//打印容器
	}
		
	if(!s2.empty()){
		cout << "s2.size= " << s2.size() << endl;
		cout << "s2: ";
		show_set(s2);
	}
	//交换两个容器 并输出交换后的结果
	cout << "swap(s1,s2)" << endl;
	cout << "s1: ";
	show_set(s1);
	cout << "s2: ";
	show_set(s2);
}

输出结果:

s1.size= 4
s1: 10 20 30 45
s2.size= 5
s2: 1 2 3 4 5
swap(s1,s2)
s1: 10 20 30 45
s2: 1 2 3 4 5

注: set容器不支持resize方法。

5. set容器的查找和统计

方法功能
find(key);查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end(),常用 判断元素是否出现等
count(key);统计key的元素个数

注:
(1)对于set容器而言,元素的值是不能重复的,因此count返回的值为1或0,key元素存在则返回1,不存在则返回0。
(2)find函数返回的是迭代器

void test()
{
	set<int> s1{2,5,3,8,0,3,6};	//构造容器并初始化
	//set容器实际排序 0 2 3 5 6 8
	//查找
	set<int>::iterator pos = s1.find(3);
	if(pos != s1.end())
		cout << "找到该元素:" << *pos << endl;
	else
		cout << "未找到该元素" << endl;
		
 	//统计个数
	int num = s1.count(3);
	if(num == 1)
		cout << "存在该元素 个数为1" << endl;
	else	
		cout << "不存在该元素 " << endl;
}

输出结果:

找到该元素:3
存在该元素 个数为1

6. set、multiset、unordered_set三者的区别

集合是否有序数值知否可重复底层实现
std::set有序不可重复红黑树
std::multiset有序可重复红黑树
std::unordered_set无序不可重复哈希表

(1)在哈希表数据结构算法中,若输出的结果是去重的, 同时可以不考虑输出结果的顺序,则优先使用unordered_set容器,底层为哈希表,相对数的查找效率更高
(2)set和multiset 在头文件 #include <set> 中,而unordered_set 在头文件 #include <unordered_set>

set容器插入数据
set.insert函数原型:

_Pairib insert(value_type&& _Val)

_Pairib定义:

using _Pairib = pair<iterator, bool>

本质上是pair,称为对组,即成对出现的一组数据,有两个数据成对出现,第一个数据是迭代器,第二个数据为bool类型的数据,定义一个对组用来接收insert的返回值

pair<set<int>::iterator, bool> ret;

获取set容器的insert插入结果

void test06()
{
	set<int> s1{2,5};	
	pair<set<int>::iterator, bool> ret = s1.insert(3);
	if(ret.second == true)	//通过ret.second 读取对组里面的第二个值
		cout << "第一次插入成功"<< endl;
	else
		cout << "第一次插入失败"<< endl;
		
	ret = s1.insert(3);
	if(ret.second == true)
		cout << "第二次插入成功"<< endl;
	else
		cout << "第二次插入失败"<< endl;
	
}

输出结果:

第一次插入成功
第二次插入失败

multiset容器插入数据

ms.insert函数原型:

iterator insert(value_type&& _Val)

multiset容器insert插入函数返回的是一个迭代器

multiset<int> ms{2,5};
ms.insert(10);
ms.insert(10);
ms.insert(10);

for(multiset<int>::iterator it=ms.begin(); it != ms.end(); it++)
	cout << *it << " ";
cout << endl;

输出结果:

2 5 10 10 10

因此如果不允许插入重复数据可以利用set,如果需要插入重复数据利用multiset

7. pair对组的创建

如果一个函数想要返回两个数据,可以考虑使用对组返回数据,两个数据分别用pair的两个公有函数 first 和 second 访问。

对组的创建:

  • pair(); 默认构造函数
  • pair<type,type> p( value1,value2); 直接使用 2 个元素初始化成 pair 对象
  • pair(const pair<U,V>& pr) 拷贝(复制)构造函数
  • pair<type,type> p = make_pair(value1,value2);
    有参构造:
pair<string, int> stu1("zhangsan", 22);

利用make_pair函数:

pair<string, int> stu2 = make_pair("lisi", 20);

数据赋值与读取:

void test07()
{
	pair<string, int> stu;							//默认构造函数
	pair<string, int> stu1("zhangsan", 22);			//有参构造
	pair<string, int> stu2 = make_pair("lisi", 20);	//使用make_pair函数
	pair<string, int> stu3(stu2); 				//拷贝(复制)构造函数
	
	stu.first = "lihua";
	stu.second = 18;			//对stu对组数据赋值
	stu3.first = "wangwu";		//修改stu3第一个数据,第二个数据拷贝的stu2
	
	//读取对组数据	
	cout << "stu name=  " << stu.first << "\tage= " << stu.second << endl;
	cout << "stu1 name= " << stu1.first << "\tage= " << stu1.second << endl;
	cout << "stu2 name= " << stu2.first << "\t\tage= " << stu2.second << endl;
	cout << "stu3 name= " << stu3.first << "\tage= " << stu3.second << endl;
}

输出结果:

8. set容器的排序

  set容器默认排序规则为从小到大,但可通过仿函数,改变排序规则。在这里仿函数不过多讲解,只进行应用,仿函数相当于重载了函数调用运算符()。

set容器存放内置数据类型

  一旦对set容器插入数据后,容器内顺序已经固定,因此要改变容器的排序顺序,应**先设定排序顺序,再插入数据**。在设置排序规则时,需要使用仿函数,因此先定义从大到小的排序仿函数。

定义仿函数

//set容器的排序
//从大到小的排序仿函数
class Myset
{
public:
	bool operator()(int v1, int v2)	//第一个()表重载的符号,第二个()是函数参数列表的括号
	{
		return v1>v2;
	}
};

定义从大到小排序的s2容器

//指定排序规则为从大到小 对s2容器起作用
set<int, Myset> s2{2,5,3,8,0,3,6};		//仿函数本质是个类型

迭代输出,注意s2的类型为set<int, Myset>,因此s2的迭代器类型也应该为set<int, Myset>

//遍历s2容器
//s2 容器类型为set<int, Myset>, 所以迭代器类型也为set<int, Myset> 
for(set<int, Myset>::iterator it = s2.begin(); it != s2.end();it++)
	cout << *it << " ";
cout << endl;

完整测试代码如下:

//set容器的排序
//从大到小的排序仿函数
class Myset
{
public:
	bool operator()(int v1, int v2)	//第一个()表重载的符号,第二个()是函数参数列表的括号
	{
		return v1>v2;
	}
};

void test()
{
	set<int> s1{2,5,3,8,0,3,6};		//构造容器并初始化
	//set容器实际排序 0 2 3 5 6 8
	cout << "---------原s1容器为: ----------" << endl;	
	show_set(s1);
	//现在s1已经确定了排序规则,无法再进行更改
	//因此要在容器插入数据之前就设置排序规则	
	//指定排序规则为从大到小 对s2容器起作用
	set<int, Myset> s2{2,5,3,8,0,3,6};		//仿函数本质是个类型
	
	//遍历s2容器
	//s2 容器类型为set<int, Myset>, 所以迭代器类型也为set<int, Myset> 
	cout << "---------新s2容器为: ----------" << endl;
	for(set<int, Myset>::iterator it = s2.begin(); it != s2.end();it++)
		cout << *it << " ";
	cout << endl;
}

输出结果:
在这里插入图片描述

set容器存放自定义数据类型

定义自定义数据类型Student

//自定义数据类型 Student
class Student{
public:
	Student();		//无参构造
	Student(string name, int age, int score, char sex);		//有参构造
	
	string name;
	int age;
	int score;
	char sex;
};

Student::Student(string name, int age, int score, char sex)
{
	this->name = name;
	this->age  = age;
	this->score = score;
	this->sex  = sex;
}

定义仿函数 根据学生成绩降序排序

//根据学生成绩从高到低排序的仿函数
class compareStudent
{
public:
	bool operator()(const Student &stu1, const Student &stu2)	//第一个()表重载的符号,第二个()是函数参数列表的括号
	{
		return stu1.score > stu2.score;
	}
};

测试案例

void test()
{
	//自定义数据 都要先指定排序规则 编译器不清楚如何排
	set<Student, compareStudent> s1;
	
	//实例化对象
	Student stu1("zhangsan", 22, 80, 'm');
	Student stu2("lisi",     20, 70, 'm'); 
	Student stu3("wangwu",   21, 95, 'm'); 
	Student stu4("chenliu",  22, 86, 'w'); 
	
	//自定义数据存入set容器
	s1.insert(stu1);
	s1.insert(stu2);
	s1.insert(stu3);
	s1.insert(stu4);
	
	//通过迭代器遍历数据
	for(set<Student, compareStudent>::iterator it = s1.begin(); it != s1.end(); it++)
		cout << "姓名: " << it->name << "\t年龄: " << it->age << "\t成绩: " << it->score << endl;
}

注: set容器插入自定义类型的数据,必须编写仿函数来确定排序的关键词和规则

输出结果:
在这里插入图片描述

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

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

相关文章

SpringSecurity+OAuth2权限管理实战

Spring Security快速入门 官方文档&#xff1a; Spring Security :: Spring Security 功能&#xff1a; 身份认证&#xff08;authentication&#xff09; 授权&#xff08;authorization&#xff09; 防御常见攻击&#xff08;protection against common attacks&#xff…

Filter 实现过滤符合条件的请求并落库

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、配置过滤器类 二、定义数据表、实体类、Mapper 2.1 DDL 2.2 实体类 2.3 Mapper 三、创建一个过滤器 四、实现 Nacos 配置…

C语言第二十一弹---指针(五)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 转移表 1、转移表 总结 1、转移表 函数指针数组的用途&#xff1a;转移表 举例&#xff1a;计算器的⼀般实现&#xff1a; 假设我们需要做一个能够进行加减…

JavaScript 弹窗(Popup Windows)

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 在互联网时代&#xff0c;弹窗是一种常见的交互方式。它可以用于显示…

C语言笔试题之二进制求和

实例要求&#xff1a; 给定2个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和&#xff1b; 案例展示&#xff1a; 实例分析&#xff1a; 1、利用strlen函数分别求出二进制字符串 a 和 b的长度&#xff1b;2、结果字符串长度为较长输入字符串加1&#xf…

数据结构入门(1)数据结构介绍

目录 前言 1. 什么是数据结构&#xff1f; 2.什么是算法&#xff1f; 3.数据结构和算法的重要性 前言 本文将开始介绍计算机里的数据结构。 数据结构是指数据对象中元素之间的关系&#xff0c;以及对这些关系的操作。数据结构可以分为线性结构和非线性结构。 线性结构是…

力扣面试题 05.06. 整数转换(位运算)

Problem: 面试题 05.06. 整数转换 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.通过将两个数进行异或操作求出两个数中不同的位(不同的位异或后为二进制1); 2.统计异或后不同的位的个数(即异或后二进制为1的个数) 复杂度 时间复杂度: O ( 1 ) O(1) O(1) 空间…

C++:STL - vector

C&#xff1a;STL - vector 构造函数修改操作push_backpop_backerase 访问操作emptyoperatror[]backfront 容量操作sizecapacityresizereserve C的vector是一种可变长度的动态数组&#xff0c;被广泛用于C编程中。它是标准模板库&#xff08;STL&#xff09;中的容器之一&#…

2024年 复习 HTML5+CSS3+移动web 笔记 之CSS遍 第6天

6.1 定位-相对和绝对和固定 6.2 相对和绝对和固定 6.3 堆叠顺序z-index 6.4 定位总结 6.5 CSS精灵 基本使用 6.6 案例 CSS精灵 京东服务 6.7 字体图标-下载和使用 6.8 字体图标-上传 6.9 垂直对齐方式vertical-align 6.10 过渡属性 6.11 修饰属性-透明度与光标类型 6.12 综合案…

react将选中文本自动滑动到容器可视区域内

// 自动滚动到可视区域内useEffect(() > {const target ref;const wrapper wrapperRef?.current;if (target && wrapperRef) {const rect target.getBoundingClientRect();const wrapperRect wrapper.getBoundingClientRect();const isVisible rect.bottom &l…

npm 上传一个自己的应用(4) 更新自己上传到NPM中的工具版本 并进行内容修改

前面 npm 上传一个自己的应用(2) 创建一个JavaScript函数 并发布到NPM 我们讲了将自己写的一个函数发送到npm上 那么 如果我们想到更好的方案 希望对这个方法进行修改呢&#xff1f; 比如 我们这里加一个方法 首先 我们还是要登录npm npm login然后 根据要求填写 Username 用…

Sping Cloud Hystrix 参数配置、简单使用、DashBoard

Sping Cloud Hystrix 文章目录 Sping Cloud Hystrix一、Hystrix 服务降级二、Hystrix使用示例三、OpenFeign Hystrix四、Hystrix参数HystrixCommand.Setter核心参数Command PropertiesFallback降级配置Circuit Breaker 熔断器配置Metrix 健康统计配置Request Context 相关参数C…

【Spring源码解读!底层原理进阶】【上】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…

【图形图像的C++ 实现 01/20】 2D 和 3D 贝塞尔曲线

目录 一、说明二、贝塞尔曲线特征三、模拟四、全部代码如下 一、说明 以下文章介绍了用 C 计算和绘制的贝塞尔曲线&#xff08;2D 和 3D&#xff09;。    贝塞尔曲线具有出色的数学能力来计算路径&#xff08;从起点到目的地点的曲线&#xff09;。曲线的形状由“控制点”决…

个体诊所门诊电子处方开单管理系统软件,配方模板病历模板设置一键导入操作教程

个体诊所门诊电子处方开单管理系统软件&#xff0c;配方模板病历模板设置一键导入操作教程 一、前言 以下操作教程以 佳易王诊所电子处方软件V17.2为例说明&#xff0c;最新版V17.3下载可以点击最下方官网卡片了解。 1、在现实生活中&#xff0c;医师开单可谓是争分夺秒&…

苏宁易购移动端首页(rem布局)

技术选型 方案∶采取单独制作移动页面方案技术:布局采取rem适配布局( less rem &#xff0b;媒体查询)设计图:设计图采用750px设计尺寸 设置视口标签以及引入初始化样式 <meta name"viewport" content"widthdevice-width, initial-scale1.0, user-scalable…

Vulnhub靶机:hacksudo-FOG

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;hacksudo-FOG&#xff08;10.0.2.48&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/…

TCP和UDP相关问题(重点)(5)——5.TCP三次握手和四次挥手(非常重要)

5.1三次握手的过程 一次握手&#xff1a;客户端发送带有SYN(x)标志的数据包到服务端&#xff0c;然后客户端进入SYN_SEND状态&#xff0c;等待服务器端的确认。 二次握手&#xff1a;服务端发送带有SYN(y)ACK(x1)标志的数据包到客户端&#xff0c;然后服务端进入SYN_RECV状态。…

SCI 1区论文:Segment anything in medical images(MedSAM)[文献阅读]

基本信息 标题&#xff1a;Segment anything in medical images中文标题&#xff1a;分割一切医学图像发表年份: 2024年1月期刊/会议: Nature Communications分区&#xff1a; SCI 1区IF&#xff1a;16.6作者: Jun Ma; Bo Wang(一作&#xff1b;通讯)单位&#xff1a;加拿大多…

负载均衡(3)

文章目录 一、HAProxy介绍企业版社区版版本对比HAProxy功能支持功能不具备的功能 二、编译安装HAProxy解决lua环境Centos 基础环境 编译安装HAProxy验证HAProxy版本HAProxy启动脚本配置文件启动haproxy验证haproxy状态查看haproxy的状态页面 三、HAProxy基础配置详解global配置…