c++STL之关联式容器

news2024/11/18 1:36:31

目录

set容器

set的默认构造

set的插入与迭代器

set集合的元素排序

set集合的初始化及遍历

从小到大(默认情况下)

 从大到小

仿函数 

set的查找

pair的使用

multiset容器 

map和multimap容器 

map的插入与迭代器

map的大小

map的删除

map的查找


关联式容器(Associated containers),元素位置取决于特定的排序准则,和插入顺序无关

在c++STL中主要有set、multiset、map、multimap

set容器

  • set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
  • set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。

set的默认构造

set<int> setInt;            //一个存放int的set容器。

set<float> setFloat;     //一个存放float的set容器。

set<string> setString;     //一个存放string的set容器。

multiset<int> mulsetInt;            //一个存放int的multi set容器。

multi set<float> multisetFloat;     //一个存放float的multi set容器。

multi set<string> multisetString;     //一个存放string的multi set容器。

set的插入与迭代器

  • set.insert(elem);     //在容器中插入元素。
  • set.begin();  //返回容器中第一个数据的迭代器。
  • set.end();  //返回容器中最后一个数据之后的迭代器。
  • set.rbegin();  //返回容器中倒数第一个元素的迭代器。
  • set.rend();   //返回容器中倒数最后一个元素的后面的迭代器。

set集合的元素排序

  • set<int,less<int> >  setIntA;  //该容器是按升序方式排列元素。
  • set<int,greater<int>> setIntB;   //该容器是按降序方式排列元素。
  • set<int> 相当于 set<int,less<int>>。
  • less<int>与greater<int>中的int可以改成其它类型,该类型主要要跟set容纳的数据类型一致。

set集合的初始化及遍历

从小到大(默认情况下)

//集合 元素唯一 自动排序 不能按照[]方式插入元素
//默认情况下是从小到大
void main91()
{
	set<int> set1;
	for (int i = 0; i < 5; i++)
	{
		int tmp = rand();
		set1.insert(tmp);
	}
	set1.insert(100);
	set1.insert(100);
	set1.insert(100);
	for (set<int>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	while (!set1.empty())
	{
		set<int>::iterator it = set1.begin();
		cout << *it << " ";
		set1.erase(set1.begin());
	}
}

 从大到小

void main92()
{
	set<int,greater<int>> set1;
	for (int i = 0; i < 5; i++)
	{
		int tmp = rand();
		set1.insert(tmp);
	}
	set1.insert(100);
	set1.insert(100);
	set1.insert(100);
	for (set<int,greater<int>>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

}

仿函数 

对于复杂的数据类型set集合是通过用户自定义来排序的,主要利用的就是仿函数这个机制。

//仿函数
struct FuncStudent
{
	bool operator()(const Student& left, const Student& right) const
	{
		if (left.m_age < right.m_age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

void main93()
{
	set<Student, FuncStudent> set1;
	Student s1("s1", 32);
	Student s2("s2", 22);
	Student s3("s3", 16);
	Student s4("s4", 55);
	Student s5("s5", 32);

	set1.insert(s1);
	set1.insert(s2);
	set1.insert(s3);
	set1.insert(s4);
	set1.insert(s5);//两个一样的值
	//如何知道插入的结果

	//遍历
	for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << it->m_age << "\t" << it->m_name << endl;
	}
}

set的查找

  • set.find(elem);   //查找elem元素,返回指向elem元素的迭代器。
  • set.count(elem);   //返回容器中值为elem的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。
  • set.lower_bound(elem);  //返回第一个>=elem元素的迭代器。
  • set.upper_bound(elem);    //  返回第一个>elem元素的迭代器。
  • set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。

pair的使用

  • pair译为对组,可以将两个值视为一个单元。
  • pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。
  • pair.first是pair里面的第一个值,是T1类型。
  • pair.second是pair里面的第二个值,是T2类型。

set<int> setInt;

...  //往setInt容器插入元素1,3,5,7,9

pair< set<int>::iterator , set<int>::iterator > pairIt = setInt.equal_range(5);

set<int>::iterator itBeg = pairIt.first;

set<int>::iterator itEnd = pairIt.second;

//此时 *itBeg==5  而  *itEnd == 7

//如何判断insert的返回值
void main94()
{
	set<Student, FuncStudent> set1;
	Student s1("s1", 32);
	Student s2("s2", 22);
	Student s3("s3", 16);
	Student s4("s4", 55);
	Student s5("s5", 32);

	pair<set<Student, FuncStudent>::iterator, bool> pair1;
	pair1 = set1.insert(s1);
	if (pair1.second)
	{
		cout << "插入s1成功" << endl;
	}
	else
	{
		cout << "插入s1失败" << endl;
	}
	set1.insert(s2);
	set1.insert(s3);
	set1.insert(s4);
	pair1 = set1.insert(s5);//两个一样的值
	if (pair1.second)
	{
		cout << "插入s5成功" << endl;
	}
	else
	{
		cout << "插入s5失败" << endl;
	}
		//遍历
	for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << it->m_age << "\t" << it->m_name << endl;
	}
}

multiset容器 

  • multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
  • 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
void main101()
{
	multiset<int> set1;
	int tmp;

	cout << "请输入multiset集合的值:";
	scanf("%d", &tmp);
	while (tmp != 0)
	{
		set1.insert(tmp);
		cout << "请输入multiset集合的值:";
		scanf("%d", &tmp);
	}

	//遍历
	for (multiset<int>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	while (!set1.empty())
	{
		multiset<int>::iterator it = set1.begin();
		cout << *it << " ";
		set1.erase(set1.begin());
	}
}

map和multimap容器 

  • map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。
  • map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。
  • map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  • multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

map的插入与迭代器

  • map.insert(...);    //往容器插入元素,返回pair<iterator,bool>
  • 在map中插入元素的三种方式:

假设  map<int, string> mapStu;

  • 一、通过pair的方式插入对象

mapStu.insert(  pair<int,string>(3,"小张")  );

  • 二、通过pair的方式插入对象

mapStu.inset(make_pair(-1, “校长-1”));

  • 三、通过value_type的方式插入对象

mapStu.insert(  map<int,string>::value_type(1,"小李")  );

  • 四、通过数组的方式插入值

mapStu[3] = “小刘";

mapStu[5] = “小王";

  • 前三种方法,采用的是insert()方法,该方法返回值为pair<iterator,bool>
  • 第四种方法非常直观,但存在一个性能的问题。插入3时,先在mapStu中查找主键为3的项,若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成“小刘”。若发现已存在3这个键,则修改这个键对应的value。
  • string strName = mapStu[2];   //取操作或插入操作
  • 只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。

map的大小

  • map.size(); //返回容器中元素的数目
  • map.empty();//判断容器是否为空

map的删除

  • map.clear(); //删除所有元素
  • map.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
  • map.erase(beg,end);     //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
  • map.erase(keyElem);     //删除容器中key为keyElem的对组。

map的查找

  • map.find(key);   查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
  • map.count(keyElem);   //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
//map的添加/遍历/删除
void main111()
{
	map<int, string> map1;
	
	//方法一
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));
	
	//方法二
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));
	
	//方法四
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	//容器的删除
	while (!map1.empty())
	{
		map<int, string>::iterator it = map1.begin();
		cout << it->first << "\t" << it->second << endl;
		map1.erase(it);
	}
}

//插入的四种方法异同
//前三种返回值是pair<iterator,bool>
//前三种方法若key已经存在则报错
//方法四    若key已经存在则覆盖
void main112()
{
	map<int, string> map1;

	//方法一
	pair<map<int, string>::iterator,bool> mypair1 = map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	//方法二
	pair<map<int, string>::iterator, bool> mypair3 = map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	pair<map<int, string>::iterator, bool> mypair5 = map1.insert(map<int, string>::value_type(5, "teacher05"));
	if (mypair5.second)
	{
		cout << mypair5.first->first << mypair5.first->second << endl;
	}
	else
	{
		cout << "key5 插入失败" << endl;
	}
	pair<map<int, string>::iterator, bool> mypair6 = map1.insert(map<int, string>::value_type(5, "teacher06"));
	if (mypair6.second)
	{
		cout << mypair6.first->first << mypair6.first->second << endl;
	}
	else
	{
		cout << "key5 插入失败" << endl;
	}
	//方法四
	map1[7] = "teacher07";
	map1[7] = "teacher77";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;
}

 

void main113()
{
	map<int, string> map1;

	//方法一
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	//方法二
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));

	//方法四
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	//map的查找
	map<int, string>::iterator it2 = map1.find(100);
	if (it2 == map1.end())
	{
		cout << "key 100的值不存在" << endl;
	}
	else
	{
		cout << it2->first << "\t" << it2->second << endl;
	}

	//equal_range
	pair<map<int, string>::iterator, map<int, string>::iterator> mypair = map1.equal_range(5);//返回两个迭代器 形成一个pair
	//第一个迭代器>=5的位置
	//第二个迭代器>5的位置
	if (mypair.first == map1.end())
	{
		cout << "第一个迭代器不存在" << endl;
	}
	else
	{
		cout << mypair.first->first << "\t" << mypair.first->second << endl;
	}

	//使用第二个迭代器
	if (mypair.second == map1.end())
	{
		cout << "第一个迭代器不存在" << endl;
	}
	else
	{
		cout << mypair.second->first << "\t" << mypair.second->second << endl;
	}
}

 

 

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

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

相关文章

【LeetCode: 337. 打家劫舍 III | 暴力递归=>记忆化搜索=>动态规划 | 树形dp】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

整数二分从入门到精通

前言&#xff1a; 开个玩笑&#xff0c;我们写算法可不能这样哈~ 好了&#xff0c;正片开始&#xff1a; 你是否曾经也有过整数二分因为一直死循环而苦恼&#xff0c;你是否因为搞不清楚整数二分的边界处理而焦躁&#xff0c;明明很简单的一道二分&#xff0c;但是最后就是搞…

Python入门教程+项目实战-9.1节: 字符串的定义与编码

目录 9.1.1 理解字符串 9.1.2 字符串的类型名 9.1.3 字符的数字编码 9.1.4 常用的字符编码 9.1.5 字符串的默认编码 9.1.6 字符串的编码与解码 9.1.7 转义字符详解 9.1.8 对字符串进行遍历 9.1.9 知识要点 9.1.10 系统学习python 9.1.1 理解字符串 理解字符串&#…

005:Mapbox GL添加全屏显示功能

第005个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中添加全屏显示功能 。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共60行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://…

还在因为写项目函数太多而烦恼?C++模板一文带你解决难题

&#x1f4d6;作者介绍&#xff1a;22级树莓人&#xff08;计算机专业&#xff09;&#xff0c;热爱编程&#xff1c;目前在c&#xff0b;&#xff0b;阶段>——目标Windows&#xff0c;MySQL&#xff0c;Qt&#xff0c;数据结构与算法&#xff0c;Linux&#xff0c;多线程&…

轮廓查找与绘制

轮廓查找与绘制 1)什么是轮廓 轮廓可以简单认为成将连续的点&#xff08;连着边界&#xff09;连在一起的曲线&#xff0c;具有相同的颜色或者灰度&#xff0c;提取轮廓就是提取 这些具有相同颜色或者灰度的曲线&#xff0c;或者说是连通域&#xff0c;轮廓在形状分析和物体…

学习系统编程No.20【进程间通信之命名管道】

引言&#xff1a; 北京时间&#xff1a;2023/4/15/10:34&#xff0c;今天起床时间9:25&#xff0c;睡了快8小时&#xff0c;昨天刷视屏刷了一个小时&#xff0c;本来12点的时候发完博客洗把脸就要睡了&#xff0c;可惜&#xff0c;看到了一个标题&#xff0c;说实话&#xff0…

.Net路由操作!!!!

什么是路由 问题 答案 路由是什么&#xff1f; 路由系统负责处理传入的请求并选择控制器和操作方法来处理它们。 路由系统还用于在视图中生成路由&#xff0c;称为传出的URL 路由有什么用&#xff1f; 路由系统能够灵活地处理请求&#xff0c;面不是将URL与Visual Studio…

MySQL(31)-ubuntu20.04-下安装mysql5.7

ubuntu20.04 下apt 默认安装的是8.0版本&#xff0c;如果要安装5.7版有如下3种方式&#xff1a; 1 下载 MySQL 二进制压缩包&#xff0c;解压并设置相关的参数即可运行 2 通过命令 apt install 进行安装&#xff0c;先下载 MySQL 5.7 对应的源&#xff0c;然后执行安装命令 ap…

5 分钟带你小程序入门 [实战总结分享]

微信小程序常常用 4 种文件类型 JS 文件 JS 在小程序中用于编写页面逻辑和交互效果&#xff0c;可调用 API 接口完成数据请求和处理&#xff0c;也可以使用第三方库和框架。 模块化编程&#xff1a;小程序中JS文件可以使用ES6的模块化语法&#xff0c;通过export和import来…

【vue3】关于watch与computed的用法看这个就ok

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;watch()与computed的使用【vue2中watch|computed概念详解】&#xff0c;本文将介绍在vue3中怎么使用这两者技能 【前言】vue2当中有这两个技能&#xff0c;那么vue3中的watch与compute…

【云原生进阶之容器】第六章容器网络6.4.1--Flannel组网方案综述

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述

【Unity】用HDRI作为Unity的Skybox

教程&#xff1a;用HDRI作为Unity的Skybox 在Unity中&#xff0c;Skybox是用于创建环境背景的一种组件。使用高动态范围图像&#xff08;HDRI&#xff09;作为Skybox可以提供更真实的环境背景。以下是使用HDRI作为Unity Skybox的步骤&#xff1a; 步骤1&#xff1a;下载HDRI图…

进销存管理系统能为企业带来哪些实际效益?

随着互联网的不断发展&#xff0c;如今的商业世界已经越来越向数字化转型。拥有一套完整的数字化的进销存管理能够极大地提升公司货物进出库存情况的效率和准确性&#xff0c;避免过程中出现不必要的错误和漏洞&#xff0c;从而帮助企业更加稳健地自我发展。那么&#xff0c;一…

华为MatePad有什么好用的软件?

现如今伴随着办公方式的转变&#xff0c;人们正迫切地寻找能够顺应时代的“生产力新工具”&#xff0c;它既要能够满足线上/线下灵活切换&#xff0c;又要具备绘画、键入、远程沟通、跨终端联动等多种功能。 对大多数人来说&#xff0c;日常使用华为平板只是满足一下娱乐和生活…

【SSA-LSTM】基于麻雀算法优化LSTM 模型预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

超详细从入门到精通,pytest自动化测试框架实战-fixture固件高级操作(十一)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 参数化fixture fix…

深度学习随笔

一、SPP的作用 解决了训练CNN需要输入图像尺寸一致的问题。 一个CNN可看作由卷积、池化、全连接层组成&#xff0c;由于全连接层的权重矩阵是一个固定值&#xff0c;因此输入全连接层的特征图的维度也必须固定。 SPP利用多尺度思想解决了上述问题&#xff0c;使得神经网络的训练…

2023/4/16总结

深刻的了解了网络编程的一些知识点 socket:套接字 ServerSocket 用来声明服务器 Socket用来声明客户端&#xff0c;其实也不然&#xff0c;在serversocket的accept的方法中&#xff0c;返回的是一个socket变量。我觉得更像一个接口&#xff0c;网络接口。 InternetAddress可以…

PaddlePaddle NLP学习笔记1 词向量

文章目录1.语言模型 Language Model1.1 语言模型是什么1.2 语言模型计算什么1.3 n-gram Language Model2.神经网络语言模型NNLM2.1 N-gram模型的问题3. 词向量3.1 词向量(word Embedding)word2vec 词向量训练算法3.2 如何把词转换为词向量&#xff1f;3.3如何让向量具有语义信息…