C++:map和set的基本使用

文章目录

  • 搜索模型
  • 关联式容器
  • set
    • set的基本使用
    • set的其他使用
  • multiset
  • map
    • map的基本使用
    • map中的[]
  • multimap

搜索模型

在实际搜索中有两个搜索模型:Key的搜索模型和Key/Value的搜索模型

Key的搜索模型:

简单来说就是在一个搜索树,搜索树中的内容是一个一个的关键值,而通过一定的查找手段可以确定一个值在不在这个树内,在实际应用情境中可以在闸机,门禁等地方遇到这个搜索模型,通过给定的信息在已有的信息库中进行搜索,如果有就同一进入,如果没有就禁止进入

Key/Value的搜索模型:

这种搜索模型有两个功能,一个功能是进行搜索Key在不在这个搜索树内,第二个功能是用来通过Key可以查找Value的值,在实际应用情景中可以在字典,统计单词出现的次数中见到,在后面也会进行一些举例来更好的理解这种场景的意义所在

关联式容器

在前面的学习中有学到过不同的容器,例如有vector list deque等,这些容器被叫做是序列式容器,原因是因为它们底层的数据结构都是线性序列的数据结构,存储的是元素的本身

关联式容器也是用来存储数据的,但是和序列式不同的是,它里面存储的是<key,value>结构的键值对,在数据检索的时候比序列式容器的效率更高一些

键值对:

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代
表键值,value表示与key对应的信息

set

对于set的定义解释:

Sets are containers that store unique elements following a specific order.

In a set, the value of an element also identifies it (the value is itself the key, of type T), and each value must be unique. The value of the elements in a set cannot be modified once in the container (the elements are always const), but they can be inserted or removed from the container.

Internally, the elements in a set are always sorted following a specific strict weak ordering criterion indicated by its internal comparison object (of type Compare).

set containers are generally slower than unordered_set containers to access individual elements by their key, but they allow the direct iteration on subsets based on their order.

Sets are typically implemented as binary search trees.

set是按照一定次序存储元素的容器,它的基本用法如下所展示:

set的基本使用

在这里插入图片描述
实现也是用模板来实现的,第一个模板参数是存储的元素类型,第二个是仿函数,第三个是空间配置器

set的基本使用

在这里插入图片描述
下面对于上面这些函数进行基本的实践和使用理解

void testset1()
{int arr[] = { 1,2,3,4,5,6,1,2,3,4 };set<int> st(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto e : st){cout << e << " ";}cout << endl;
}

上面的样例构造了一个set,并将其中的内容进行了输出,输出结果是1 2 3 4 5 6,说明它包含了去重和排序的功能

insert的使用

在cplusplus中,对于insert的定义如下:

在这里插入图片描述
insert有三种用法,一种是直接插入一个值,在前文定义中提到value_type实际上是The first template parameter (T),也就是第一个模板参数,那么就默认可以把这个当成是set中存储的元素类型,也就是直接向set中插入一个元素,而函数的返回值是一个键值对,键值对中第一个数据是一个迭代器,第二个数据是布尔值,在文档中对于其定义如下:

The single element versions (1) return a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the equivalent element already in the set. The pair::second element in the pair is set to true if a new element was inserted or false if an equivalent element already existed.

The versions with a hint (2) return an iterator pointing to either the newly inserted element or to the element that already had its same value in the set.

Member type iterator is a bidirectional iterator type that points to elements.
pair is a class template declared in (see pair).

简单来说就是,第一种版本的函数,其成员pair::first被设置为一个迭代器,该迭代器指向新插入的元素或集合中已经存在的等效元素。如果插入了新元素,则pair::中的第二个元素设为true;如果已经存在等效元素,则设为false

第二个版本的函数返回一个迭代器,该迭代器指向新插入的元素或在集合中已经具有相同值的元素

第三个版本的函数是通过迭代器来进行插入的

在这里插入图片描述
从测试的函数结果可以看出,和预期的结果是一样的,使用版本1的函数如果插入成功则pair的返回值是true,如果插入失败返回的是false,迭代器指向的位置就是插入元素的位置

find的使用和前面的STL容器基本相同,如果找到了返回该位置的迭代器,如果没找到返回end(),下面利用find函数来进行特定位置的插入

	// 在迭代器所指示的位置插入一个元素set<int>::iterator it3 = st.find(1);if (it3 != st.end()){st.insert(it3, 10);}

erase的用法:

在这里插入图片描述
erase函数版本1的参数时一个迭代器,返回值为空,版本2的参数是一个值,返回的值是删除元素的数量

void testset3()
{int arr[] = { 1,2,3,4,5,6 };set<int> st(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto e : st){cout << e << " ";}cout << endl;set<int>::iterator it = st.find(2);if (it != st.end()){st.erase(it);}cout << st.erase(3) << endl;
}

set的其他使用

前面的使用在vector和list等序列式容器中其实也有这样的操作,总体来说大差不差,但是set是一个关联式容器,因此它是有一些前面没有见过的内容和操作的

lower_bound和upper_bound:

在这里插入图片描述
在这里插入图片描述
简单来说,这两个函数可以构造出一个迭代器区间,lower_bound返回的是第一个大于等于val值的位置,而upper_bound返回的是第一个大于val值的位置,因此可以用这个构造出一个迭代器区间,可以供给erase来使用

void testset4()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };set<int> st(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto e : st){cout << e << " ";}cout << endl;set<int>::iterator lowit = st.lower_bound(2);set<int>::iterator upit = st.upper_bound(5);// 构造出要删除的区间是[2,5]st.erase(lowit, upit);for (auto e : st){cout << e << " ";}cout << endl;
}

因此输出结果为

1 2 3 4 5 6 7 8 9 10
1 6 7 8 9 10

equal_range的使用:
在这里插入图片描述
获取相等元素的范围
返回一个范围的边界,该范围包括容器中与val等效的所有元素。

因为set容器中的所有元素都是唯一的,所以返回的范围最多只包含一个元素。

如果没有找到匹配项,则返回的范围长度为0,两个迭代器都指向容器内部比较对象(key_comp)认为在val之后的第一个元素。

如果容器的比较对象自反性地返回false(即,无论元素作为参数传递的顺序如何),则认为集合中的两个元素相等。

在这里插入图片描述

该函数返回一个pair,其成员pair::first是范围的下界(与lower_bound相同),pair::second是上界(与upper_bound相同)。

成员类型iterator和const_iterator是指向元素的双向迭代器类型。

// set::equal_elements
void testset5()
{std::set<int> myset;for (int i = 1; i <= 5; i++) myset.insert(i * 10);   // myset: 10 20 30 40 50std::pair<std::set<int>::const_iterator, std::set<int>::const_iterator> ret;ret = myset.equal_range(30);std::cout << "the lower bound points to: " << *ret.first << '\n';std::cout << "the upper bound points to: " << *ret.second << '\n';
}

multiset

下面介绍的是multiset

在这里插入图片描述
对于这个容器来说,它是一个简单的排序的作用,并不会有去重的效果,如果有多个值,find返回中序第一个val,multiset在底层实际存储的是<int, int>的键值对,其他整体来说区别不算很大

map

在这里插入图片描述

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))

在这里插入图片描述

从中看出,map中使用的就是Key_Value搜索模型,在传参的时候也需要传递两个参数

map的基本使用

insert的使用
在这里插入图片描述
结合上面的定义表可以看到,在map中的value_type实际上是一个键值对类型,也就是说在插入元素的时候每次要插入的都是一个键值对类型的元素,下面演示两种insert的插入方法

void testmap1()
{map<string, string> mp;// 1. 构造对象mp.insert(pair<string, string>("sort", "排序"));mp.insert(pair<string, string>("insert", "插入"));// 2. 函数调用mp.insert(make_pair("left", "左边"));
}

通常来说使用函数调用来构造一个pair对象更好一些

map中的[]

在序列式容器中,[]通常是用作运算符重载来看的,可以用于数据的随机存取,但是在map中并非如此,map中的[]的功能扩展很多:

在这里插入图片描述
下面用例子来说明map中[]的多种使用场景

在这里插入图片描述
在文档中有这样的一句话

A call to this function is equivalent to:
(*((this->insert(make_pair(k,mapped_type()))).first)).second

那么对这句进行解析:(*((this->insert(make_pair(k,mapped_type()))).first)).second

在理解这句前,要首先知道insert调用的结果是pair<iterator,bool> insert (const value_type& val),返回的是一个pair键值对,这里通过this指针调用了insert函数,再对所得到的键值对取它的first元素,也就是迭代器,再对迭代器进行解引用,迭代器指向的就是插入元素的位置,对迭代器的second解引用得到的就是Key_Value中的Value值

因此通过[]得到的返回值其实是通过Key来访问到Value值,如果没有Key会优先创建出Key的值,再对Value值进行一些访问修改等操作…

  1. map中的的元素是键值对
  2. map中的key是唯一的,并且不能修改
  3. 默认按照小于的方式对key进行比较
  4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
  5. map的底层为平衡搜索树(红黑树),查找效率比较高
  6. 支持[]操作符,operator[]中实际进行插入查找

multimap

  1. Multimaps是关联式容器,它按照特定的顺序,存储由keyvalue映射成的键值对<key,value>,其中多个键值对之间的key是可以重复的
  2. multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。keyvalue的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合keyvalue的键值对:typedef pair<const Key, T>value_type
  3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的
  4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列
  5. multimap在底层用二叉搜索树(红黑树)来实现。注意:multimapmap的唯一不同就是:map中的key是唯一的,而multimapkey是可以
    重复的

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

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

相关文章

汽车EDI:福特Ford EDI项目案例

项目背景 福特&#xff08;Ford&#xff09;是世界著名的汽车品牌&#xff0c;为美国福特汽车公司&#xff08;Ford Motor Company&#xff09;旗下的众多品牌之一。此前的文章福特FORD EDI需求分析中&#xff0c;我们已经了解了福特Ford EDI 的大致需求&#xff0c;本文将会介…

【Linux】jdk、tomcat、MySQL环境搭建的配置安装,Linux更改后端端口

一、作用 工具的组合为开发者和系统管理员提供了构建和运行Java应用程序以及存储和管理数据的完整环境。 JDK&#xff08;Java Development Kit&#xff09;&#xff1a;JDK是Java开发工具包&#xff0c;它提供了开发和运行Java应用程序所需的工具和库。通过安装JDK&#xff0c…

SolidWorks2019安装教程(正版)

网盘资源附文末 一.简介 SolidWorks软件是世界上第一个基于Windows开发的三维CAD系统&#xff0c;由于技术创新符合CAD技术的发展潮流和趋势&#xff0c;SolidWorks公司于两年间成为CAD/CAM产业中获利最高的公司。良好的财务状况和用户支持使得SolidWorks每年都有数十乃至数百…

Mac-Java开发环境安装(JDK和Maven)

JDK安装 1、访问oracle官网&#xff0c;下载jdk 点击下载链接&#xff1a;https://www.oracle.com/java/technologies/downloads/#java11-mac 选择Mac版本&#xff0c;下载dmg 打勾点击下载&#xff0c;跳转登陆&#xff0c;没有就注册&#xff0c;输入账号密码即可下载成功…

Ubuntu20.04安装CUDA、cuDNN、tensorflow2可行流程(症状:tensorflow2在RTX3090上运行卡住)

最近发现我之前在2080ti上运行好好的代码&#xff0c;结果在3090上运行会卡住很久&#xff0c;而且模型预测结果完全乱掉&#xff0c;于是被迫研究了一天怎么在Ubuntu20.04安装CUDA、cuDNN、tensorflow2。 1.安装CUDA&#xff08;包括CUDA驱动和CUDA toolkit&#xff0c;注意此…

ajax-axios发送 get请求 或者 发送post请求带有请求体参数

/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */ !function(e,t){"object"typeof exports&&"object"typeof module?module.exportst():"function"typeof define&&define.amd?define([],t):"object"typeof export…

【WinForm详细教程四】WinForm中的ProgressBar 、ImageList和ListView控件

文章目录 1.ProgressBar2. ImageList3.ListView控件 1.ProgressBar 用于显示某个操作的进度。 属性&#xff1a; Value: 表示当前进度条的值&#xff0c;其范围由Min和Max决定。Step: 设置每次调用PerformStep()方法时增加的步长。MarqueeAnimationSpeed: 在Style设置为Marq…

RabbitMQ 运维 扩展

1、集群管理与配置 1.1、集群搭建 关于Rabbitmq 集群的搭建&#xff0c;详见以下文章。简单说来就是将多个单机rabbitmq服务&#xff0c;通过给到一致的密钥&#xff08;.erlang.cookie&#xff09;并且开放rabbitmq服务的 25672 端口&#xff0c;允许多节点间进行互相通讯&am…

iptables 与 firewalld

iptables 一、主机型&#xff08;包过滤防火墙&#xff09; 1、简介&#xff1a; 包过滤型防火墙是一种网络安全设备或软件&#xff0c;它工作在 2、3、4 层&#xff0c;通过检查网络数据包的源地址、目标地址、协议、端口等信息&#xff0c;根据预定义的规则来决定是否允许…

ip划分与私公网ip、ip的传递

报文问路&#xff1a;1、不知道跳转默认路由器&#xff0c;2、知道路径&#xff0c;向对应路径发出报文&#xff0c;3、路口路由器&#xff0c;下一步就是目标主机在哪。 想要通信必须同在一个局域网&#xff0c;其实将公网就可以看作一个大型的局域网。 在同一个局域网内发送…

正点原子嵌入式linux驱动开发——Linux USB驱动

USB是很常用的接口&#xff0c;目前大多数的设备都是USB接口的&#xff0c;比如鼠标、键盘、USB摄像 头等&#xff0c;在实际开发中也常常遇到USB接口的设备&#xff0c;本章就来学习一下如何使能Linux内核自带的USB驱动。这里不会具体学习USB的驱动开发。 USB接口简介 什么是…

413 Request Entity Too Large(nginx/1.24.0)

报错内容 <html><head><title>413 Request Entity Too Large</title></head><body><center><h1>413 Request Entity Too Large</h1></center><hr><center>nginx/1.24.0</center></body>&…

Explaining and harnessing adversarial examples

Explaining and harnessing adversarial examples----《解释和利用对抗样本》 背景&#xff1a; 早期的研究工作认为神经网络容易受到对抗样本误导是由于其非线性特征和过拟合。 创新点&#xff1a; 该论文作者认为神经网络易受对抗性扰动影响的主要原因是它的线性本质&#xf…

精通Nginx(03)-配置简述

本文主要讲述Nginx配置文件结构及调试技巧 使用nginx版本为1.24.0。 目录 Nginx目录 nginx.conf内容结构 配置片段化 配置调试技巧 Nginx目录 Nginx编译安装目录如下&#xff1a; 安装指定目录为"/usr/local"。配置目录为/usr/local/nginx/conf。 目录说明&am…

用LibreOffice在excel中画折线图

数据表格如下。假设想以x列为横坐标&#xff0c;y1和y2列分别为纵坐标画折线图。 选择插入-》图表&#xff1a; 选择折线图-》点和线&#xff0c;然后点击“下一步”&#xff1a; 选择&#xff1a;列中包含数据序列&#xff0c;然后点击完成&#xff08;因为图挡住了数据…

浏览器哪家强——PC端篇

今天的分享将围绕一个大家再熟悉不过的名称展开——浏览器。 根据百科给出的解释&#xff1a;浏览器是用来检索、展示以及传递Web信息资源的应用程序。通俗的说&#xff0c;浏览器就是一种阅读工具&#xff0c;类似记事本、word、wps&#xff0c;只不过后者阅读的是文本文档&am…

记一次 logback 没有生成独立日志文件问题

背景 在新项目发布后发现日志文件并没有按照期望的方式独立开来&#xff0c;而是都写在了 application.log 文件中。 问题展示 日志文件&#xff1a; 项目引入展示&#xff1a; <include resource"paas/sendinfo/switch/client/sendinfo-paas-switch-client-log.…

初识JavaScript(一)

文章目录 一、JavaScript介绍二、JavaScript简介1.ECMAScript和JavaScript的关系2.ECMAScript的历史3.什么是Javascript&#xff1f;4.JavaScript的作用?5.JavaScript的特点 三、JavaScript基础1.注释语法2.JavaScript的使用 四、JavaScript变量与常量变量关键字var和let的区别…

npm install报错,解决记录

第一步&#xff1a;检查和安装 我这里建议检查 1.node.js版本是否和前使用版本一致 2.npm版本是否和前使用版本一致 3.vue版本是否和前使用版本一致 4.vue脚手架是否和前使用版本一致 5.npm镜像是否和前使用版本一致 1.检查版本 【node版本】 命令&#xff1a;node -v 结果&a…

删除排序链表中的重复节点II(C++解法)

题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5]示例 2&#xff1a; 输入&#xff1a;head [1…