【C++】set与map的使用

目录

一、set:

1、set介绍:

2、常用构造:

3、常用修改操作:

(1)insert:

(2)find

(3)erase:

4、其他操作:

(1)count:

(2)lower_bound、upper_bound:

multiset:

二、map:

1、map介绍:

2、常用构造:

3、常用修改操作:

(1)insert、emplace:

(2)find:

(3)erase:

4、其他操作:

(1)count:

(2)lower_bound、upper_bound:

multimap:


一、set:

1、set介绍:

        set是按照一定次序存储元素的容器,它用于存储唯一的元素(即在容器中没有重复的元素)通常用于需要快速查找、插入和删除元素的场景,底层通常是用红黑树来实现这些操作的快速性。

特点:

  1. 在set中的元素都具有唯一性,也就是set会自动排序+去重,默认按照升序排序。
  2. 往set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. 可以使用set的迭代器遍历set中的元素,即可得到升序的有序序列。
  4. set的查找效率是非常高效的:O(logN),底层由红黑树实现(高度次查找)。

2、常用构造:

void Test1()
{
	vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };
	
	set<int> s1(v.begin(), v.end()); // 区间构造

	set<int> s2(s1); // 拷贝构造

	set<int> s3;  s3 = s2; // 赋值重载

	// 遍历可得升序的去重序列
    for (auto e : s1)
	{
		cout << e << " ";
	}
	cout << endl;
}

3、常用修改操作:

(1)insert:

set的插入操作就只用insert就可以了,因为无论从哪个位置插入,最终都会被排序好。至于去重的功能,就是在树中(set的底层就是红黑树)如果已存在要插入的值,则取消插入操作。

void Test2()
{
	set<int> s;
	s.insert(6);
	s.insert(3);
	s.insert(8);
	s.insert(7);
	s.insert(6);
	s.insert(9);
	s.insert(0);
	s.insert(3);
	s.insert(7);
	s.insert(5);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

(2)find

find查找找到了返回指定值位置的迭代器,找不到返回end();

void Test4()
{
	vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };
	set<int> s(v.begin(), v.end());

	auto it = s.find(3);
	cout << *it << endl; // 输出3

	auto it2 = s.find(20);
	if (it2 == s.end()) cout << "it2 == s.end()" << endl;

}

(3)erase:

erase 的三种删除:

指定位置删除:s.erase(iterator)

指定区间删除:s.erase(first,second) 

指定值删除:s.erase(val);

void Test3()
{
	vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };
	set<int> s(v.begin(), v.end());
	cout << "s:";
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// s.erase(iterator)
	cout << "s.erase(iterator): erase(begin()): ";
	s.erase(s.begin());
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// s.erase(val)
	cout << "s.erase(val): val = 6: ";
	s.erase(6);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// s.erase(first, second),
	cout << "s.erase(first,second): erase(s.begin(),s.end()) : ";
	s.erase(s.begin(),s.end());
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl; 
	cout << "因为区间删除全删了,所以set中没有元素";
}

4、其他操作:

(1)count:

count(val) 的操作就是在容器中查找是否有值val,如果有返回1,没有返回0。

(2)lower_bound、upper_bound:

lower_bound(key_value)返回第一个大于等于key_value的定位器

upper_bound(key_value)返回第一个大于key_value的定位器

失败都返回end( );    可以理解为两者分别是一个开、闭区间【   )

void Test6()
{
	vector<int> v = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	set<int> s(v.begin(), v.end());
	cout << "s: ";
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl << endl;
	// 可以配合erase实现区间删除的功能
	s.erase(s.lower_bound(3), s.upper_bound(9));
	
	cout << "删除区间3 ~ 9:  ";
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

multiset:

        前面说到set会自动去重,但是如果不想让其去重的话可以使用multiset,从用法上来讲和set差别不大,但是不会去重,在插入时可以默认相同值往右插入,但是也可能会旋转到左分支去,在查找并返回时,为了配合删除但不影响整棵树的原则,默认是找中序遍历的第一个值,也就是说找到该值后你还不能停,还要去你的左子树看看还有没有相同值,因为中序遍历就是左中右形式。

二、map:

1、map介绍:

        map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素。它包含可以重复的键值对(key-value pairs),但每个键(key)在map中是唯一的。map提供了一种从键(key)映射到值(value)的方式,其中键用于唯一标识元素,而值是与该键相关联的数据。

特点:

  1. map中的元素总是按照键值key进行比较排序的。
  2. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序 对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  3. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  4. map和set一样会通过键值key去重操作。

2、常用构造:

void map1()
{
	map<string, int> m1; // 无参构造

	// 传入键值对构造
	map<string, int> m2 = { {"zhangsan",1 }, { "lisi",2 }, { "wangwu",3 } }; 

	// 迭代器区间构造:
	vector<pair<string, int>> p = { {"zhangsan",1 }, { "lisi",2 }, { "wangwu",3 } };
	map<string, int> m3(p.begin(), p.end());

	map<string, int> m4(m3); // 拷贝构造

	map<string, int> m5 = m4; // 赋值重载

	// 遍历:
	for (auto e : m5)
	{
		cout << e.first << " : " << e.second << endl;
	}
}

可以看到map默认以key值升序排序(也就是按照e.first升序排序)

3、常用修改操作:

(1)insert、emplace:

map的插入主要通过insert插入和emplace插入:

insert方法接受一个 pair<const Key, T>的值(或可以隐式转换为该值的对象),其中Key是键的类型,T是值的类型。

emplace方法则是直接在 map 中构造元素,而不是首先创建一个临时的pair对象。这通常可以减少不必要的拷贝或移动操作,从而提高效率。特别是当构造pair对象本身需要执行大量工作时(例如,当值类型涉及大量计算或内存分配时),使用emplace可以显著提高性能。

void map2()
{
	map<string, int> m1;
	m1["zhangsan"] = 1; m1["lisi"] = 2; m1["wangwu"] = 3; // 也可以通过此方法插入,底层的[]是重载了的

	map<string, int> m2;
	m2.insert(pair<string, int>("zhangsan", 1));
	
	m2.insert(make_pair("lisi", 2));

	// 上面的两种插入比较繁杂,所以一般使用以下简洁的写法
	m2.insert({ "wangwu",3 });

	m2.emplace("zhaoliu", 4);

	for (auto e : m2)
	{
		cout << e.first << " : " << e.second << endl;
	}
}

(2)find:

find查找找到了返回指定key值位置的迭代器,找不到返回end();

(3)erase:

erase 的三种删除:

指定位置删除:m.erase(iterator)

指定区间删除:m.erase(first,second) 

指定key值删除:m.erase(key);

void map4()
{
	map<string, int> m;
	m["liuyi"] = 1; m["chener"] = 2; m["zhangsan"] = 3; 
	m["lisi"] = 4; m["wangwu"] = 5; m["zhaoliu"] = 6;

	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << endl;

	m.erase(m.begin());
	cout << "m.erase(iterator): erase(begin())" << endl;
	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << endl;

	cout << "m.erase(key): key = zhangsan" << endl;;
	m.erase("zhangsan");
	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << endl;

	cout << "erase(first,second): erase(begin(), end())" << endl;
	m.erase(m.begin(), m.end());
	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << "因为进行begin() ~ end()的删除,所以map中已经没有元素" << endl;
}

4、其他操作:

(1)count:

count(key) 的操作就是在容器中查找是否有键值key,如果有返回1,没有返回0。

(2)lower_bound、upper_bound:

lower_bound(key_value)返回第一个大于等于key_value的定位器

upper_bound(key_value)返回第一个大于key_value的定位器

失败都返回end( );    可以理解为两者分别是一个开、闭区间【   )

void map7()
{
	map<string, int> m;
	m["liuyi"] = 1; m["chener"] = 2; m["zhangsan"] = 3;
	m["lisi"] = 4; m["wangwu"] = 5; m["zhaoliu"] = 6;

	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << endl;

	// 同样可以配合erase达到删除区间的目的:
	m.erase(m.lower_bound("lisi"), m.upper_bound("zhansan"));

	for (auto& e : m)
	{
		cout << e.first << " : " << e.second << endl;
	}
	cout << endl;
}

multimap:

        和multiset一样,取消了去重功能,可以加入重复key值的键值对,道理同前面讲multiset时的差不多,所以这里不再赘述。

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

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

相关文章

【linuxC语言】守护进程

文章目录 前言一、守护进程的介绍二、开启守护进程总结 前言 在Linux系统中&#xff0c;守护进程是在后台运行的进程&#xff0c;通常以服务的形式提供某种功能&#xff0c;如网络服务、系统监控等。守护进程的特点是在启动时脱离终端并且在后台运行&#xff0c;它们通常不与用…

docker系列9:容器卷挂载(下)

传送门 docker系列1&#xff1a;docker安装 docker系列2&#xff1a;阿里云镜像加速器 docker系列3&#xff1a;docker镜像基本命令 docker系列4&#xff1a;docker容器基本命令 docker系列5&#xff1a;docker安装nginx docker系列6&#xff1a;docker安装redis docker系…

Vue Cli脚手架—安装Nodejs和Vue Cli

一&#xff0c;Vue Cli 文档地址: https://cli.vuejs.org/zh/ 二&#xff0c;.环境配置&#xff0c;搭建项目 1.安装node.js 2.下载 node.js10.16.3 地址: https://nodejs.org/en/blog/release/v10.16.3/ 3.安装 node.js10.16.3 , 直接下一步即可, 安装到 d:\program\nodejs…

iOS 创建依赖其他开源库的开源库

参考文章&#xff08;感激各位大神前路的明灯&#xff09; 参考文章一 参考项目 整体流程 流程简介 1&#xff09;使用pod命令行创建本地项目和git仓库并回答终端里的四个问题 2&#xff09;编辑podspec文件 3&#xff09;将需要开源的代码添加到Development Pods文件夹中&am…

Python量化炒股的获取数据函数—get_fundamentals_continuously()

Python量化炒股的获取数据函数—get_fundamentals_continuously() get_fundamentals()函数只能用于查询某一交易日的股票财务数据信息&#xff0c;如果要查询多个交易日的股票财务数据信息&#xff0c;就要使用get_fundamentals_continuously()函数&#xff0c;语法格式如下&a…

[方法] Unity 实现仿《原神》第三人称跟随相机 v1.0

参考网址&#xff1a;【Unity中文课堂】RPG战斗系统Plus 在Unity游戏引擎中&#xff0c;实现类似《原神》的第三人称跟随相机并非易事&#xff0c;但幸运的是&#xff0c;Unity为我们提供了强大的工具集&#xff0c;其中Cinemachine插件便是实现这一目标的重要工具。Cinemachi…

手机配置在线检测工具微信小程序源码

手机配置在线检测工具微信小程序源码&#xff0c;这是一款升级版检测工具&#xff0c;自动检测手机真伪,序列号等。另外还可以给手机检测各项功能是否正常。 支持多做流量主模式,还有外卖CPS,和友情小程序推荐等 源码免费下载地址 抄笔记(chaobiji.cn)

Servlet(一些实战小示例)

文章目录 一、实操注意点1.1 代码修改重启问题1.2 Smart Tomcat的日志1.3 如何处理错误 一. 抓自己的包二、构造一个重定向的响应&#xff0c;让页面重定向到百度主页三、让服务器返回一个html数据四、表白墙4.1 约定前后端数据4.2 前端代码4.3 后端代码4.4 保存在数据库的版本…

【学习vue 3.x】(二)组件应用及单文件组件

文章目录 章节介绍本章学习目标学习前的准备工作Vue.js文件下载地址 组件的概念及组件的基本使用方式组件的概念组件的命名方式与规范根组件局部组件与全局组件 组件之间是如何进行互相通信的父子通信父子通信需要注意的点 组件的属性与事件是如何进行处理的组件的属性与事件 组…

软件测试(实验五)——Jmeter的使用

目录 实验目的 一、使用JMeter演示取样器、监听器、配置元件、断言的使用&#xff1b; 1、取样器 2、监听器 3、配置元件的使用 ① 用户定义的变量 ②HTTP信息头管理器 ③HTTP请求默认值 ④CSV数据文件设置 4、断言 ①响应断言 ②JSON断言 ③断言持续时间 二、使用…

C语言之位操作符:<<、>>、、|、^、~,以及原码反码补码和例题详解

目录 前言 一、原码、反码、补码 二、移位操作符 三、位操作符&#xff1a;&、|、^、~ 四、经典例题分析&#xff1a; 总结 前言 本文将详细介绍C语言中左移操作符<<&#xff0c;右移操作符>>&#xff0c;按位与&&#xff0c;按位或|&#xff0c;按位异或^…

【QT学习】14补充,使用线程制作绘图工具

思路&#xff1a; 结果&#xff1a; 点击刷新图片&#xff0c;自动绘制一个六点连接图 线程类的属性 线程类的函数实现 void MyThread::drawImage(){//Qimage设备QImage image(600,600,QImage::Format_ARGB32);//画家QPainter p(&image);//画笔&#xff0c;画刷QPen pen;pe…

进位计数制

目录 前言 最古老的计数方法 十进制数 推广:r 进制计数法 任意进制->十进制 二进制<->八进制,十六进制 十进制->任意进制 真值和机器数 总结: 前言 本篇文章我们正式进入第二章:数据的表示和运算,通过第一章的学习我们知道了现代计算机的结构 那数据如何…

基于php+mysql+html图书管理系统(含实训报告)

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、Php、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

自然语言处理 (NLP) 中的迁移学习

--懂王 在大数据高速发展的时代&#xff0c;AI的发展日新月异&#xff0c;充满挑战的迎接未来。 自然语言处理 (NLP) 中的迁移学习: 迁移学习在 NLP 中越来越受欢迎&#xff0c;特别是在数据稀缺的情况下。如何有效地利用预训练的语言模型&#xff0c;并将其迁移到新的任务和领…

kubectl_入门_service详解

Service 我们知道 Pod 的生命周期是有限的。可以用 ReplicaSet 和Deployment 来动态的创建和销毁 Pod&#xff0c;每个 Pod 都有自己的 IP 地址&#xff0c;但是如果 Pod 重建了的话那么他的 IP 很有可能也就变化了。 这就会带来一个问题&#xff1a;比如我们有一些后端的 Po…

基于Springboot的教学资源共享平台(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的教学资源共享平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

【Cpp】类和对象#构造函数 析构函数

标题&#xff1a;【Cpp】类和对象#构造函数 析构函数 水墨不写bug &#xff08;图片来源于网络&#xff09; 正文开始&#xff1a; &#xff08;一&#xff09;构造函数 构造函数是特殊的成员函数&#xff0c;需要注意的是&#xff0c;构造函数虽然名称叫构造&#xff0c;但…

nginx变量自定义日志收集

内置变量 $remote_addr&#xff1b;存放了客户端的地址&#xff0c;注意是客户端的公网IP&#xff0c;也就是一家人访问一个网站&#xff0c;则会显示为路由器的公网IP。 $args&#xff1b;变量中存放了URL中的指令 [rootlocalhost conf.d]# cat pc.conf server {listen 80;se…

数组的扩容与缩容

数组的扩容与缩容 文章目录 数组的扩容与缩容数组的扩容内存分析 数组的缩容内存分析内存分析 数组的扩容 数组扩容是指当原有数组的空间不足以容纳更多的元素时&#xff0c;创建一个新的、长度更大的数组&#xff0c;并将原数组中的元素复制到新数组中&#xff0c;然后更新原…