C++ set map 详解

文章目录

  • 1. 容器
  • 2. set和multiset
    • 2.1 set
      • 2.1.1 构造函数
      • 2.1.2 insert和erase
        • 2.1.2.1 insert
        • 2.1.2.2 erase
      • 2.1.3 查找和访问
        • 2.1.3.1 set迭代器相关
        • 2.1.3.2 find && count
        • 2.1.3.3 范围查找
    • 2.2 multiset
      • 2.2.1 insert和erase
      • 2.2.2 find和count
    • 2.3 set和multiset的在算法题中的应用
  • 3. map和multimap
    • 3.1 pair介绍
    • 3.2 map
      • 3.2.1 构造函数
      • 3.2.2 insert和erase
      • 3.2.3 find和count
      • 3.2.4 operator[] 和 at
    • 3.3 multimap

1. 容器

在C++的stl中,容器分为序列式容器和关联式容器。

对于序列式容器而言,容器的逻辑结构是线性的,相邻两个位置的数据之间,没有较为紧密的联系,因此通常是可以交换的。对于这类容器的数据访问,一般都是通过数据存储的位置进行访问,最典型的例子,如vector

对于关联式容器,容器的逻辑结构是非线性的,相邻两个位置的数据之间,是有紧密的联系,通常是不可以交换的,一旦交换,便会破坏整个容器的结构。像map和set,就是关联式容器的代表,这类容器中数据的访问,一般都是借助于key,即键值来进行访问的。

2. set和multiset

2.1 set

set的底层是不支持键值冗余的二叉搜索树,存储的是key,而非key-value
以下,我们介绍使用set容器时,几个非常重要的接口。

2.1.1 构造函数

set的构造函数,有三个是比较重要的。

一个是默认构造。

在这里插入图片描述
默认构造中,关于内存池的形参一般不用在意,除非有别的内存池可以供你调用。
set中的仿函数需要注意,默认的仿函数进行的是小于的比较,因此,默认对整个set容器的遍历,是依据键值得到的升序。如果想要得到降序,可以传入一个进行大于比较的仿函数。

一个是使用迭代器进行构造。

在这里插入图片描述

还有一个是在C++11中引入的,使用初始化列表这种容器进行构造。

在这里插入图片描述

2.1.2 insert和erase

2.1.2.1 insert

在set中,我们使用insert来进行键值的插入。

较为常用的主要是三个:直接插入键值的,插入迭代器区间的,插入初始化列表的。

直接插入键值的:

在这里插入图片描述
我们主要看第一个左值引用,第二个右值引用暂不做讨论。
这个函数重载就是直接插入键值,比较特殊的是它的返回值,返回的是一个pair类型。

在这个pair类型中,有两个成员,第一个成员是set的迭代器,第二个成员是bool型的变量。

由于set是不允许键值冗余的二叉搜索树,因此set是存在插入失败的情况。在插入成功时,pair中包含插入位置对应的迭代器,以及一个true;插入失败时,返回二叉搜索树中某个已存在key值的迭代器(此key值与所要插入的key值相同),以及一个false。

其余的两种形式:

在这里插入图片描述

2.1.2.2 erase

在这里插入图片描述
erase有三种删除形式,其中前两种使用得最多。

iterator erase(const_iterator position):这是利用迭代器进行删除,删除的是迭代器所对应的key,返回值也是一个迭代器——一般是返回删除元素的后一个迭代器,但如果删除的元素后面没有元素,那就返回set.end()

size_type erase (const value_type& val): 这是利用键值去删除。在删除前,先要找到键值对应的具体位置,然后再删除。这个返回值很特殊,是删除的数据个数。这让人有点疑惑,set既然是不支持冗余的,那么删除的数据个数最多只是1,设计这样的返回值感觉没什么用——实际上,这是在设计上与multiset进行一个统一,对于multiset,这个返回值是有意义的。

iterator erase(const_iterator first,const_iterator last):删除一段迭代器区间。

2.1.3 查找和访问

2.1.3.1 set迭代器相关

set的迭代器使用和其它容器一样,这里不做赘述。

在这里插入图片描述
需要注意的是,虽然set中也区分了const迭代器和非const迭代器,但是无论是哪种迭代器,都是不能对set中的键值进行修改,因为一旦修改,就很可能破坏整棵二叉搜索树的结构。

在这里插入图片描述

2.1.3.2 find && count

在这里插入图片描述
利用键值进行查找,返回相应位置的迭代器,对应的有const迭代器和非const迭代器两个版本。

在这里插入图片描述
count是去查找set中相应键值的元素个数,这个在set中不是0,就是1,最主要还是在multiset中的使用,不过在设计时,考虑到set和multiset的协同,因此set中也有这个函数。

2.1.3.3 范围查找

在这里插入图片描述
范围查找lower_bound和upper_bound配套使用

在这里插入图片描述

在这里插入图片描述

对于lower_bound,返回的是整棵二叉搜索树中大于或等于传入val的第一个数据的迭代器;对于upper_bound,返回的是整棵二叉搜索树中大于传入val的第一个数据的迭代器(这里之所以是大于val,缘于迭代器的使用规则,因为迭代器遍历的循环条件总是!= 某个迭代器)。如果这样的数据不存在,那么这两个函数都是返回set.end()

除了上述的用于查找某个范围的两个函数,还有一个用于查找相同键值范围的函数,这个函数在set中没有啥意义,在multiset中才比较有用。

在这里插入图片描述
这个equal_range函数返回的是一个pair类型,存储对应某个范围的左右两个边界的迭代器,注意,右迭代器对应这个范围之后的第一个元素(或是set.end())。如果key值不存在,则pair中的两个成员变量均为set.end()。

2.2 multiset

相较于set,multiset是支持键值冗余的搜素二叉树。
multiset整体的成员函数于set相类似,不过由于其支持键值冗余的特性,在部分函数上会有所差别。

2.2.1 insert和erase

在这里插入图片描述
对于insert,由于multiset允许键值冗余,所以不存在插入失败的情况,因此直接返回插入位置对应的迭代器即可。

在这里插入图片描述
对于erase,如果使用的是迭代器版本,那么就是将相应位置的元素清除;如果使用传val值的版本,则会将multiset中,所有等于该键值的数据全部删除,并返回删除的数据个数。

2.2.2 find和count

在这里插入图片描述
multiset中,存在键值冗余的情况,那么这个find,究竟是查找哪一个数据呢?
find函数默认查找的是整棵二叉搜索树的中序遍历中的键值与val相等的第一个数。

在这里插入图片描述
count函数即返回整棵二叉搜索树中,与val相等的键值的个数。

2.3 set和multiset的在算法题中的应用

set是非键值冗余的二叉搜索树,而二叉搜索数的中序遍历又是有序的,所以,我们如果要对一系列数据进行去重+排序处理,那么就可以将这些数据放至set容器中,否则就需要使用算法库中的sort+unique。

multiset是键值冗余的二叉搜索树,如果仅需要实现排序功能,而不需去重,可将数据放至multiset中。

3. map和multimap

map和multimap,底层都是key-value的二叉搜索树,map允许键值冗余,multimap不允许键值冗余。由于key-value需要存储两个数,所以map和multimap底层存放的数据类型是pair,默认pair类型中的第一个成员是key,第二个成员是value。

3.1 pair介绍

pair是用于存储成对的,并且往往有关联的两个数据,分别存储到pair的first成员和second成员中,这两个成员是允许类外直接访问的。

pair中,最重要的便是如何去构造出一个pair对象,以下介绍几种常用的方法。

在这里插入图片描述

pair类型的对象也可以进行大小的比较,重载了相关的运算符。

pair类型对象的比较,先比较成员first,再比较成员second。

  • 相等比较:两个成员都相等,则相等。
  • 大于比较:谁first大,谁就大;first一样大,再比较second,谁second大,谁就大。
  • 小于比较:与大于比较逻辑相同,比大转为比小即可。
  • 不等于比较:两个成员有一个不相等,便不相等。

3.2 map

3.2.1 构造函数

map的常用构造与set类似,默认构造、拷贝构造和使用一段迭代器区间进行构造。

需要注意的是,由于map的底层数据是pair类型的,因此使用一段迭代器区间进行构造时,迭代器指向的一定要是pair类的对象。

3.2.2 insert和erase

map的insert需要插入一个pair对象。

在这里插入图片描述
最常见的插入还是单元素的插入,这种插入通常习惯以下两种写法:

在这里插入图片描述

map的erase:

在这里插入图片描述
size_type erase(const key_type& k) : map中的erase是按照key值来删除,而非value。

3.2.3 find和count

在这里插入图片描述
在这里插入图片描述
均是按照键值key来进行查找和统计

3.2.4 operator[] 和 at

方括号在map中的重载,是map中非常重要的一个成员函数,功能也较为复杂。

在这里插入图片描述
operator[ ]的重载,需要传一个key值(key_type)进去,返回的是key值相应的value值的引用(mapped_type)。

但实际上,这个重载函数远没有看上去那么简单。这个函数的使用,要分为两种情况:

  • 相应的key值存在。此时返回key值相应的val值的引用。
  • 相应的key值不存在。此时并不会查找失败,这个函数会调用insert向map中再插入一个pair对象,这个pair对象的key值是传入的key值,value值是利用map中的value类型构造出的匿名对象,然后函数再返回这个value值。

实质上,在相应的key值存在时,函数也会调用insert,只不过会插入失败,不过由于即便插入失败,insert也会返回相应key值对应的迭代器(返回是pair类型,迭代器为其第一个成员),因此可以正常返回相应value值的引用。

以下是stl库中,map容器中operator[ ]函数的实现:

mapped_type& operator[] (const key_type& k)
{pair<iterator, bool> ret = insert({ k, mapped_type() });iterator it = ret.first;return it->second;
}

at与operator[ ]类似,传key值,返回value值,只不过at只能用于已存在的key值查找,不能用于插入不存在的key值,当输入一个不存在的key值时,at函数会抛异常。

在这里插入图片描述
以下举一个使用operator[ ]进行次数统计的典型例子:

在这里插入图片描述
在main函数中调用,相应的输出为:

在这里插入图片描述

3.3 multimap

与map相比较,multimap 是支持键值冗余的key-value二叉搜索树。

multimap与map的差别,同multiset与set的差异相类似,此处不再赘述。

有一点需要注意,map是不支持键值冗余,但是value值是可以相同的,只要相应的key值不同即可;而multimap对于key和value则都是没有限制的。

另外,在multimap中没有了operator[ ]和at这两个成员函数,最主要的原因还是在于键值冗余,因此会无法解决到底返回哪个value值的问题。

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

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

相关文章

Unity网络开发基础 (2) 网络协议基础

本文章不作任何商业用途 仅作学习与交流 部分图片来自Unity唐老师 目录 1.虚拟模型 2.实际模型 TCP/IP 3.传输层协议 TCP/UDP TCP 协议详解 1. 核心机制 2. 头部格式&#xff08;20 字节最小&#xff09; UDP 协议详解 1. 核心特点 2. 头部格式&#xff08;固定 8 字节…

HTML label 标签使用

点击 <label> 标签通常会使与之关联的表单控件获得焦点或被激活。 通过正确使用 <label> 标签&#xff0c;可以使表单更加友好和易于使用&#xff0c;同时提高整体的可访问性。 基本用法 <label> 标签通过 for 属性与 id 为 username 的 <input> 元素…

JDBC、MyBatis 、MyBatis-Plus面试总结(一)

以下为你整理了一些 MyBatis 和 MyBatis-Plus 中 mapper.xml 相关的常见面试问题及答案&#xff1a; 基础概念类 问题 1&#xff1a;什么是 mapper.xml 文件&#xff0c;它在 MyBatis 中有什么作用&#xff1f; 答案&#xff1a;mapper.xml 文件是 MyBatis 中用于定义 SQL 语…

GCC RISCV 后端 -- GCC Passes 注释

在前面文章提到&#xff0c;当GCC 前端完成对C源代码解析完成后&#xff0c;就会使用 处理过程&#xff08;Passes&#xff09;机制&#xff0c;通过一系列的处理过程&#xff0c;将 GENERIC IR 表示的C程序 转步转换成 目标机器的汇编语言。过程描述如下图所示&#xff1a; 此…

基于Python实现的智能旅游推荐系统(Django)

基于Python实现的智能旅游推荐系统(Django) 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat 系统功能实现 总体设计 系统实现 系统首页模块 统首页页面主要包括首页&#xff0c;旅游资讯&#xff0c;景点信息…

鸿蒙全栈开发 D2

课程目标 掌握ArkTS基础语法与核心概念理解声明式UI开发范式能独立开发简单鸿蒙应用组件建立规范的代码编写习惯 第一部分&#xff1a;初识ArkTS 1.1 语言全景认知 #mermaid-svg-V5mnjQN3DAHkfoBo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size…

【YashanDB认证】yashandb23.3.1 个人版单机部署安装实践

YCA报名链接如下: YashanDB|崖山数据库系统YashanDB学习中心-YCA认证详情 目前免费 主要参考文档&#xff1a; 单机&#xff08;主备&#xff09;部署 | YashanDB Doc 另外还参考摩天轮文章&#xff1a; YashanDB 23.2.9.101 企业版安装步骤抢先看&#xff01; - 墨天轮 …

【蓝桥杯】每天一题,理解逻辑(3/90)【Leetcode 快乐数】

闲话系列&#xff1a;每日一题&#xff0c;秃头有我&#xff0c;Hello&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;,我是IF‘Maxue&#xff0c;欢迎大佬们来参观我写的蓝桥杯系列&#xff0c;我好久没有更新博客了&#xff0c;因为up猪我寒假用自己的劳动换了…

爬虫Incapsula reese84加密案例:Etihad航空

声明: 该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关 一、找出需要加密的参数 1.js运行 atob(‘aHR0cHM6Ly93d3cuZXRpaGFkLmNvbS96aC1jbi8=’) 拿到网址,F12打开调试工具,随便搜索航班,切换到network搜索一个时间点可以找…

缓存雪崩 缓存击穿 缓存穿透

1. redis使用场景-缓存-缓存穿透 在实际开发中&#xff0c;Redis 被广泛应用于缓存&#xff0c;以提高系统性能和响应速度。然而&#xff0c;在使用缓存时&#xff0c;需要注意一些问题&#xff0c;其中 缓存穿透 是一个常见且需要重点关注的场景。 什么是缓存穿透 ● 缓存穿…

【YOLOv12改进trick】多尺度大核注意力机制MLKA模块引入YOLOv12,实现多尺度目标检测涨点,含创新点Python代码,方便发论文

🍋改进模块🍋:多尺度大核注意力机制(MLKA) 🍋解决问题🍋:MLKA模块结合多尺度、门控机制和空间注意力,显著增强卷积网络的模型表示能力。 🍋改进优势🍋:超分辨的MLKA模块对小目标和模糊目标涨点很明显 🍋适用场景🍋:小目标检测、模糊目标检测等 🍋思路…

better-sqlite3之exec方法

在 better-sqlite3 中&#xff0c;.exec() 方法用于执行包含多个 SQL 语句的字符串。与预编译语句相比&#xff0c;这种方法性能较差且安全性较低&#xff0c;但有时它是必要的&#xff0c;特别是当你需要从外部文件&#xff08;如 SQL 脚本&#xff09;中执行多个 SQL 语句时。…

电路基础:【1】PN结二极管制作电桥点亮LED灯

第一章&#xff1a;PN结二极管制作电桥点亮LED灯 文章目录 第一章&#xff1a;PN结二极管制作电桥点亮LED灯前言一、电路原理二、电路图与元器件1.电路图 做实验总结 前言 在本章中&#xff0c;我们将探讨如何通过PN结二极管制作电桥电路&#xff0c;并利用该电路点亮LED灯。L…

XHR请求解密:抓取动态生成数据的方法

在如今动态页面大行其道的时代&#xff0c;传统的静态页面爬虫已无法满足数据采集需求。尤其是在目标网站通过XHR&#xff08;XMLHttpRequest&#xff09;动态加载数据的情况下&#xff0c;如何精准解密XHR请求、捕获动态生成的数据成为关键技术难题。本文将深入剖析XHR请求解密…

机器学习数学基础:42.AMOS 结构方程模型(SEM)分析的系统流程

该流程图完整呈现了 AMOS 结构方程模型&#xff08;SEM&#xff09;分析的系统流程&#xff0c;具体步骤及内涵如下&#xff1a; 1. 模型设定 基于理论基础或研究假设&#xff0c;构建结构方程模型的初始框架&#xff0c;明确潜变量与显变量的关系、测量模型&#xff08;因子…

以太网通讯

接口开发笔记-WebApi-CSDN博客 以太网常用通讯协议 1、modbus tcp using EasyModbus; using System;class Program {static void Main(string[] args){// 创建Modbus客户端实例ModbusClient modbusClient new ModbusClient("192.168.1.100"); // IP地址modbusCli…

Arcgis中添加脚本工具箱

文章目录 准备资料1、打开arcmap2、找到目录窗口3、复制粘贴工具箱的路径4、添加或者确认python脚本路径准备资料 (1)工具箱 (2)python脚本 1、打开arcmap 2、找到目录窗口 3、复制粘贴工具箱的路径 4、添加或者确认python脚本路径 脚本上右键属性(注意:脚本内容和路径…

TDengine SQL查询语法

简介 TDengine 中的查询 SQL 基本遵循 MYSQL 的查询语法&#xff0c;大部分查询都是通过超级表按时间维度进行的各种查询。 TDengine 时序数据库以时间为主索引列进行数据组织排序及存储&#xff0c;同时按存储块做了预计算&#xff0c;所以在无普通列过滤的 SQL 查询语句中聚…

Apache nifi demo 实验

Apache nifi 是个数据流系统&#xff0c;可以通过配置 自定义的流程来实现数据的转换。 比如可以配置一个流程&#xff0c;读取数据库里的数据&#xff0c;再转换&#xff0c;最后保存到本地文件。 这样可以来实现一些数据转换的操作&#xff0c;而不用特地编写程序来导入导出。…

javascript一些原生方法记录

Element.scrollIntoView() Element 接口的 scrollIntoView() 方法会滚动元素的父容器&#xff0c;使被调用 scrollIntoView() 的元素对用户可见。 structuredClone() 方法 Window 接口的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝。