二十三、集合类

Ⅰ . Set 类

01 Set 介绍

template < class T,                     // set::key_type/value_type
           class Compare = less<T>,     // set::key_compare/value_compare
           class Alloc = allocator<T>   // set::allocator_type
           > class set;

通过插入新的元素来扩展容器,通过插入的元素数量来增加容器的大小。

因为集合中的元素是唯一的,插入操作会检查每个插入的元素是否等同于已经存在于容器中的元素。

如果是,则不插入该元素,返回到这个现有元素的迭代器。

在内部,集合容器保持着其所有元素按照比较对象的标准进行排序,这些元素总是按照这个排序插入到它各自的位置, Set 是 排序 + 去重。

官方文章介绍:https://cplusplus.com/reference/set/set/

Set 底层是平衡二叉搜索树,是基于红黑树实现的

02 元素的插入

下面我们使用 insert 接口,来实现一下 Set 的插入

pair<iterator,bool> insert (const value_type& val);
iterator insert (iterator position, const value_type& val);
 
template <class InputIterator>  
    void insert (InputIterator first, InputIterator last);

代码演示:

void test_set1()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

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

int main()
{
	test_set1();
	return 0;
}

运行结果如下:

我们可以 发现 Set 确实具有去重的效果,这和集合是一样的,集合元素具有唯一性。

所以,如果要插入的元素是已经存在于 Set 中的,就不会再插入了。

同时,Set 还会自动排好序,默认是按升序排列的。

03 Set 支持范围 for

既然 Set 支持迭代器,那自然也是支持范围 for 的,毕竟从底层的角度来说,范围 for 其实就是迭代器。

代码演示:

void test_set1()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	for (auto e : s)
	{
		cout << e << " ";
	}
	//set<int>::iterator it = s.begin();
	//while (it != s.end())
	//{
	//	cout << *it << " ";
	//	++it;
	//}
	cout << endl;
}

运行结果如下:

04 元素的查找

再介绍一下 find 接口,如果这个元素被找到就会返回 val 的迭代器,否则就会返回 end。

iterator find (const value_type& val) const;

代码演示:

void test_set2()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	set<int>::iterator pos = s.find(5);
	if (pos != s.end())
	{
		cout << "找到了" << endl;
	}
}

运行结果如下:

05 判断元素是否在集合中

有时我们需要判断元素在不在集合中,使用 count 往往比 find 更方便。

size_type count (const value_type& val) const;

在集合中则返回1,不在则返回0。

代码演示:

void test_set3()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	if (s.count(5))
	{
		cout << "存在" << endl;
	}
}

运行结果如下:

 这里如果使用 find 的话,还需要判断 s.find(5) != s.end()。

06 元素的删除

erase 支持三种,分别是在某个位置删除,删除一个值和删除一个区间。

void erase (iterator position);
size_type erase (const value_type& val);
void erase (iterator first, iterator last);

代码演示:

void test_set4()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	cout << "当前集合元素: ";
	for (auto e : s) {
		cout << e << " ";
	}
	cout << endl;

	int x = 0;
	while (1) {
		cout << "请输入要删除的元素:";
		cin >> x;

		// 查看要删除的元素在不在集合中
		set<int>::iterator pos = s.find(x);
		if (pos != s.end()) {
			// 在集合中,删除
			s.erase(pos);
			cout << "成功删除: " << x << endl;

			// 打印删除后的结果
			cout << "删除后: ";
			for (auto e : s) {
				cout << e << " ";
			}
			cout << endl;
		}
		else {
			// 不在集合中,提示删除失败
			cout << "删除失败!" << x << "不在集合中。" << endl;
		}
	}
}

运行结果如下:

也可以直接给 erase 一个值进行删除,这个用法比较简单。

代码演示:

void test_set5()
{
	set<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	cout << "当前集合元素: ";
	for (auto e : s) 
	{
		cout << e << " ";
	}
	cout << endl;

	s.erase(3);  
	cout << "删除后: ";
	for (auto e : s) 
	{
		cout << e << " ";
	}
	cout << endl;
}

运行结果如下:

07 区间查找:lower_bound 和 upper_bound 接口

iterator lower_bound(const key_type& key);

lower_bound() 用于在指定区域内查找不小于目标值的第一个元素,返回一个指向集合中第一个大于等于给定值的元素的迭代器,如果没有找到,则返回 end

代码演示:用 lower_bound 查找第一个不小于 25 的元素

int main()
{
	set<int> s = { 10,20,30,40,50 };
	auto it = s.lower_bound(25);

	if (it != s.end()) {
		cout << "第一个不小于 25 的元素是: " << *it << endl;
	}
	else {
		cout << "未找到不小于 25 的元素" << endl;
	}
	return 0;
}

运行结果如下:

lower_bound(25) 会返回一个指向集合中第一个不小于 25 的迭代器。在上面的集合中,第一个不小于 25 的元素是 30,所以输出的结果是 30

这个可以用来干什么呢?如果我们想删除大于等于 x 的所有元素,我们就可以用它和区间删除的办法来实现。

代码演示:删除大于等于 x 的所有元素

void test_set6() 
{
	set<int> s = { 10, 20, 30, 40, 50 };
	cout << "删除前: ";
	for (auto e : s) 
	{
		cout << e << " ";
	} 
	cout << endl;

	int x = 0;
	cout << "请输入x: ";
	cin >> x;

	auto it = s.lower_bound(x);  // 找到第一个不小于x的元素
	s.erase(it, s.end());        // 迭代器区间删除

	cout << "删除后: ";
	for (auto e : s) 
	{
		cout << e << " ";
	} 
	cout << endl;
}

运行结果如下:

接收到 x 的值为 30 之后,从 lower_bound 的位置开始作为迭代器的起始位置,end 作为结束位置,调用迭代器版本的 erase 就可以实现 30,40,50 全部删除的效果。

另外一个 upper_bound 接口,则是在指定范围内查找大于目标值的第一个元素,不包含等于。

代码演示:

void test_set7()
{
	set<int> s = { 10, 20, 30, 40, 50 };
	cout << "删除前: ";
	for (auto e : s) 
	{
		cout << e << " ";
	} 
	cout << endl;

	int x = 0, y = 0;
	cin >> x >> y;
	auto left_it = s.lower_bound(x);
	auto right_it = s.upper_bound(y);
	s.erase(left_it, right_it);

	cout << "删除后: ";
	for (auto e : s) 
	{
		cout << e << " ";
	} 
	cout << endl;
}

运行结果如下:

Ⅱ . multiset 类

01 不去重的 Set

如果我们想让 Set 不去重,我们可以使用 multiset,使用方法和 Set 大差不差。

Set 是排序 + 去重,但 multiset 是排序 + 不去重,也就是说 multiset 允许元素重复

02 multiset 的用法

multiset 就在 Set 类中,所以头文件就是 #include <set> 

代码演示:multiset 的插入

void test_set8()
{
	multiset<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

运行结果如下:

可以看到,是不去重的,就给你排个序,已经有的元素也会继续插入。

03 multiset 的删除

因为 Set 不重复,所以 erase 就删除指定元素,但 multiset 是允许冗余的。

所以 multiset 的 erase 接口会把所有指定元素删掉:

void test_set9()
{
	multiset<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);

	cout << "删除前: ";
	for (auto e : s) 
	{
		cout << e << " ";
	}
	cout << endl;

	s.erase(3);    // 会把所有的3都杀了

	cout << "删除后: ";
	for (auto e : s) 
	{
		cout << e << " ";
	}
	cout << endl;
}

运行结果如下:

04 multiset 的查找

multiset 的 find 如果要查找的元素在集合中有多个,会返回中序的第一个,假设我们要 find(3):

 代码演示:

void test_set10()
{
	multiset<int> s;
	s.insert(4);
	s.insert(8);
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(3);
	s.insert(3);

	for (auto e : s) 
	{
		cout << e << " ";
	}
	cout << endl;

	// 返回的是中序的第一个
	auto pos = s.find(3);
	while (pos != s.end()) 
	{
		cout << *pos << " ";
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5.5.1 面向对象的基本概念

文章目录 基本概念面向对象的5个原则 基本概念 面向对象的方法&#xff0c;特点时其分析与设计无明显界限。虽然在软件开发过程中&#xff0c;用户的需求会经常变化&#xff0c;但客观世界对象间的关系是相对稳定的。对象是基本的运行实体&#xff0c;由数据、操作、对象名组成…

在线免费快速无痕去除照片海报中的文字logo

上期和大家分享了用photoshop快速无痕去除照片海报中的文字logo的方法&#xff0c;有的同学觉得安装PS太麻烦&#xff0c;有那下载安装时间早都日落西山了&#xff0c;问有没有合适的在线方法可以快速去除&#xff1b;达芬奇上网也尝试了几个网站&#xff0c;今天分享一个对国人…

Linux网络 | 网络层IP报文解析、认识网段划分与IP地址

前言&#xff1a;本节内容为网络层。 主要讲解IP协议报文字段以及分离有效载荷。 另外&#xff0c; 本节也会带领友友认识一下IP地址的划分。 那么现在废话不多说&#xff0c; 开始我们的学习吧&#xff01;&#xff01; ps&#xff1a;本节正式进入网络层喽&#xff0c; 友友们…

【深度学习】DeepSeek模型介绍与部署

原文链接&#xff1a;DeepSeek-V3 1. 介绍 DeepSeek-V3&#xff0c;一个强大的混合专家 (MoE) 语言模型&#xff0c;拥有 671B 总参数&#xff0c;其中每个 token 激活 37B 参数。 为了实现高效推理和成本效益的训练&#xff0c;DeepSeek-V3 采用了多头潜在注意力 (MLA) 和 De…

STM32 PWM驱动舵机

接线图&#xff1a; 这里将信号线连接到了开发板的PA1上 代码配置&#xff1a; 这里的PWM配置与呼吸灯一样&#xff0c;呼吸灯连接的是PA0引脚&#xff0c;输出比较单元用的是OC1通道&#xff0c;这里只需改为OC2通道即可。 完整代码&#xff1a; #include "servo.h&quo…

51单片机 02 独立按键

一、独立按键控制LED亮灭 轻触按键&#xff1a;相当于是一种电子开关&#xff0c;按下时开关接通&#xff0c;松开时开关断开&#xff0c;实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 #include <STC89C5xRC.H> void main() { // P20xFE;while(1){…

本地部署 DeepSeek-R1:简单易上手,AI 随时可用!

&#x1f3af; 先看看本地部署的运行效果 为了测试本地部署的 DeepSeek-R1 是否真的够强&#xff0c;我们随便问了一道经典的“鸡兔同笼”问题&#xff0c;考察它的推理能力。 &#x1f4cc; 问题示例&#xff1a; 笼子里有鸡和兔&#xff0c;总共有 35 只头&#xff0c;94 只…

[EAI-027] RDT-1B,目前最大的用于机器人双臂操作的机器人基础模型

Paper Card 论文标题&#xff1a;RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation 论文作者&#xff1a;Songming Liu, Lingxuan Wu, Bangguo Li, Hengkai Tan, Huayu Chen, Zhengyi Wang, Ke Xu, Hang Su, Jun Zhu 论文链接&#xff1a;https://arxiv.org/ab…

DeepSeek为什么超越了OpenAI?从“存在主义之问”看AI的觉醒

悉尼大学学者Teodor Mitew向DeepSeek提出的问题&#xff0c;在推特上掀起了一场关于AI与人类意识的大讨论。当被问及"你最想问人类什么问题"时&#xff0c;DeepSeek的回答直指人类存在的本质&#xff1a;"如果意识是进化的偶然&#xff0c;宇宙没有内在的意义&a…

在 crag 中用 LangGraph 进行评分知识精炼-下

在上一次给大家展示了基本的 Rag 检索过程&#xff0c;着重描述了增强检索中的知识精炼和补充检索&#xff0c;这些都是 crag 的一部分&#xff0c;这篇内容结合 langgraph 给大家展示通过检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;的工作流&am…

UE5.3 C++ CDO的初步理解

一.UObject UObject是所有对象的基类&#xff0c;往上还有UObjectBaseUtility。 注释&#xff1a;所有虚幻引擎对象的基类。对象的类型由基于 UClass 类来定义。 这为创建和使用UObject的对象提供了 函数&#xff0c;并且提供了应在子类中重写的虚函数。 /** * The base cla…

知识库管理在提升企业决策效率与知识共享中的应用探讨

内容概要 知识库管理是指企业对内部知识、信息进行系统化整理和管理的过程&#xff0c;其重要性在于为企业决策提供了坚实的数据支持与参考依据。知识库管理不仅能够提高信息的获取速度&#xff0c;还能有效减少重复劳动&#xff0c;提升工作效率。在如今快速变化的商业环境中…

Linux:线程池和单例模式

一、普通线程池 1.1 线程池概念 线程池&#xff1a;一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价&…

AJAX笔记原理篇

黑马程序员视频地址&#xff1a; AJAX-Day03-01.XMLHttpRequest_基本使用https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p33https://www.bilibili.com/video/BV1MN411y7pw?vd_sour…

ComfyUI安装调用DeepSeek——DeepSeek多模态之图形模型安装问题解决(ComfyUI-Janus-Pro)

ComfyUI 的 Janus-Pro 节点&#xff0c;一个统一的多模态理解和生成框架。 试用&#xff1a; https://huggingface.co/spaces/deepseek-ai/Janus-1.3B https://huggingface.co/spaces/deepseek-ai/Janus-Pro-7B https://huggingface.co/spaces/deepseek-ai/JanusFlow-1.3B 安装…

3D图形学与可视化大屏:什么是材质属性,有什么作用?

一、颜色属性 漫反射颜色 漫反射颜色决定了物体表面对入射光进行漫反射后的颜色。当光线照射到物体表面时&#xff0c;一部分光被均匀地向各个方向散射&#xff0c;形成漫反射。漫反射颜色的选择会直接影响物体在光照下的外观。例如&#xff0c;一个红色的漫反射颜色会使物体在…

JVM方法区

一、栈、堆、方法区的交互关系 二、方法区的理解: 尽管所有的方法区在逻辑上属于堆的一部分&#xff0c;但是一些简单的实现可能不会去进行垃圾收集或者进行压缩&#xff0c;方法区可以看作是一块独立于Java堆的内存空间。 方法区(Method Area)与Java堆一样&#xff0c;是各个…

租赁管理系统在促进智能物业运营中的关键作用和优化策略分析

租赁管理系统在智能物业运营中的关键作用与优化策略 随着科技的飞速发展&#xff0c;租赁管理系统在智能物业运营中扮演着越来越重要的角色。这种系统不仅提高了物业管理的效率&#xff0c;更是促进了资源的优化配置和客户关系的加强。对于工业园、产业园、物流园、写字楼和公…

LLMs之DeepSeek:Math-To-Manim的简介(包括DeepSeek R1-Zero的详解)、安装和使用方法、案例应用之详细攻略

LLMs之DeepSeek&#xff1a;Math-To-Manim的简介(包括DeepSeek R1-Zero的详解)、安装和使用方法、案例应用之详细攻略 目录 Math-To-Manim的简介 1、特点 2、一个空间推理测试—考察不同大型语言模型如何解释和可视化空间关系 3、DeepSeek R1-Zero的简介&#xff1a;处理更…

【课题推荐】基于t分布的非高斯滤波框架在水下自主导航中的应用研究

水下自主导航系统在海洋探测、环境监测及水下作业等领域具有广泛的应用。然而&#xff0c;复杂的水下环境常常导致传感器输出出现野值噪声&#xff0c;这些噪声会严重影响导航信息融合算法的精度&#xff0c;甚至导致系统发散。传统的卡尔曼滤波算法基于高斯噪声假设&#xff0…