当前位置: 首页 > news >正文

【C++】map和set用法详解

文章目录

  • 1.关联式容器
  • 2.键值对
  • 3.树形结构的关联式容器
    • 3.1 set
      • 3.1.1 set的介绍
      • 3.1.2 set的模板参数列表
      • 3.1.3 set的使用
    • 3.2 map
      • map的介绍
      • map的模板参数列表
      • map的使用
      • 关于map的元素访问总结
    • 3.3multimap

1.关联式容器

我们接触过STL中的部分容器,比如:vector,list,deque,forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那么什么是关联式容器?它与序列式容器有什么区别?

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

2.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该单词,在词典就可以找到与其对应的中文含义;比如每个学生的学号跟他的姓名,年龄,专业(类型可定义成数组)存在对应关系,找到学号,就可以查到这个学生的相关信息。

SGI-STL中关于键值对的定义:

//STL中关于键值对的定义
template<class T1,class T2>
struct pair
{typedef T1 first_type;typedef T2 first_type;T1 first;T2 second;//构造函数初始化pair():first(T1())//key,second(T2())//value{}//拷贝构造函数,使用实例pair<string,int>pair(const T1& a,const T2& b):first(a),second(b){}
};

3.树形结构的关联式容器

根据应用场景不同,STL总共实现了两种不同结构的关联式容器:树形结构与哈希结构。树形结构的关联式容器主要有四种:map,set,multimap,multiset。这四种容器的共同点是:使用平衡二叉树(即红黑树)作为底层,容器中的元素是一个有序的序列。下面依次介绍每一个容器。

3.1 set

3.1.1 set的介绍

1.set翻译为集合,是一个内部自动有序且不含重复元素的关联式容器。当我们想要去重,就可以利用到set,是一个很直观的接口,并且加入set之后可以实现自动排序,需要注意的是set的元素默认按照小于比较。
2、在set中,每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以在容器中插入或删除数据。一般的做法是先删除旧元素,然后添加新元素,这当然是为了维护里面元素的有序性。
3.set在底层使用二叉搜索树(红黑树)实现的。
4.与map/multimap不同,map/multimap中存储的是真正的键值对<key,value>,而set中只放value,但在底层实际存放的是由<value,value>构成的键值对。
5.在set中查找某个元素,时间复杂度为:log2N

3.1.2 set的模板参数列表

//头文件
#include<set>
std::set
template<class T,class Compare = less<T>,class Alloc = allocator<T>>

T:set中存放元素的类型,实际在底层存储<value, value>的键值对。
Compare(仿函数):set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

3.1.3 set的使用

点此进入->set的文档

我在下列代码一一解释了关于set常见的函数该如何使用,

#include<iostream>
#include<set>
using namespace std;
int main()
{set<int> myset;//定义//迭代器的使用set<int>::iterator itlow, itup;for (int i = 1; i < 10; i++){//插入数据//注意set会将元素自动排序myset.insert(i * 10);//10 20 30 40 50 60 70 80 90}//删除35-75之间的数据itlow = myset.lower_bound(35);//返回第一个大于等于key_value的定位器itup = myset.upper_bound(75);//返回最后一个小于等于key_value的定位器//注意:set中的删除操作不进行错误检查,所以用的时候最好用一下find()函数,//返回给定值定位器,如果没找到则返回end()。myset.erase(itlow, itup);/*for (auto it = myset.begin(); it != myset.end(); ++it){cout << *it <<' ';}*///这里可以使用范围for,需要加&,因为拷贝也是存在一定代价的,不需要修改的话,也尽量加const//范围for的底层是迭代器,操作由编译器完成for (auto& s : myset){cout << s << ' ';}cout << endl;//count() 用来查找set中某个键值出现的次数。这个函数在set并不是很实用,在map中的用处比较大//因为一个键值在set只可能出现0或1次,==这样就变成了判断某一键值是否在set出现过==。cout << myset.count(100) << endl;//0不存在cout << myset.count(30) << endl;//1存在return 0;
}

3.2 map

map的介绍

点此进入->map的官方文档

1.map是关联式容器,它按照特定的次序(按照key来排序),存储由key和value组合而成的元素。
2.map中,是真正的键值对<key,value>,键值key和值value的类型可能不同,并且在map内部,key与value通过成员类型value_type绑定在一起,取名为pair。

typedef pair<const key,T> value_type
  1. 在内部,map中的元素总是按照键值key进行比较排序的。
  2. map支持下标访问,即在[]中放入key,就可以找到与key对应的value。在map中key不允许修改,key对应的value可以修改。
  3. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

map的模板参数列表

相比set,map多了一个参数

#include<map>
std::map
template<class key,class T,class Compare = less<key>,class Alloc = allocator<pair<const Key,T>>

key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的
空间配置器
注意:在使用map时,需要包含头文件。

map的使用

map的官方文档已包括所有关于map的接口函数,现在我们来尝试使用它的常用接口。
最重要的应该有:插入函数insert,[ ]下标访问操作符,对于pair的理解,迭代器的使用,删除函数。

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{//定义一个map对象map<int, string> Stu;//1.用insert函数插入pairStu.insert(pair<int, string>(01, "张三"));Stu.insert(pair<int, string>(02, "李四"));Stu.insert(pair<int, string>(03, "王五"));//但是我们发现在这里,写一个pair很不方便,因此我们可以用make_pair//make_pair的底层:是一个函数模板,还是调用pair去构造/*template<class T1,class T2>pair<T1,T2> make_pair(T1 x,T2 y){return (pair<T1, T2>(x, y));}*/Stu.insert(make_pair(04, "李芳"));//3.第三种用[]的方式插入数据Stu[123] = "王五";//4.map的迭代器//map<int, string>::iterator it = Stu.begin();auto it = Stu.begin();while (it != Stu.end()){cout << it->first << ":" << it->second << endl;++it;}//最好加上引用,如果不修改的话,把const加上更好for (const auto& kv : Stu){cout << kv.first << ":"<< kv.second << endl;}cout << endl;return 0;
}

活学活用:统计水果出现的次数

//利用map,统计水果出现的次数string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap;for (auto& e: arr){//map<string, int>::iterator it = countMap.find(e);auto it = countMap.find(e);//find函数找不到则返回end()if (it == countMap.end()){countMap.insert(make_pair(e,1));}else{it->second++;}}//有个更简洁的方法//for (auto& e : arr)//{//	countMap[e]++;//}for (const auto& e : countMap){cout << e.first << ":" << e.second;}

关于map的元素访问总结

  1. map中的元素是键值对,我们需要学习pair,然后学会使用map容器,插入数据,管理数据。
  2. map中的key是唯一的,并且不能修改
  3. map默认按照小于(升序)的方式,并且是对key排序的。map中的元素如果用迭代器去遍历,是采用中序遍历的方式,可以得到一个有序序列。
  4. map的底层是一个平衡二叉树(红黑树),查找效率很高O(logN)
  5. map中[ ]下标访问操作符是一个大头,它支持查找,修改,插入。operator[ ]向map中插入元素的原理:用<key,T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中,map中的键值对key一定是唯一的,如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器。如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器。
  6. operator[ ]函数最后将insert返回值键值对中的value返回。(也就是pair类中的second成员)
  7. 注意:在元素访问时,有一个与operat[ ]类似的函数,是at()函数,但是这个函数不常用,它们都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]会用默认的pair插入,返回该默认的value,而at()函数会直接抛异常。
  8. operator[]底层实现如下->
    在这里插入图片描述

3.3multimap

注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。

multimap中的接口可以参考map,功能都是类似的。
注意:

  1. multimap中的key是可以重复的。
  2. multimap中的元素默认将key按照小于来比较。
  3. multimap中没有重载operator[]操作。
  4. 使用时与map包含的头文件相同。

相关文章:

【C++】map和set用法详解

文章目录1.关联式容器2.键值对3.树形结构的关联式容器3.1 set3.1.1 set的介绍3.1.2 set的模板参数列表3.1.3 set的使用3.2 mapmap的介绍map的模板参数列表map的使用关于map的元素访问总结3.3multimap1.关联式容器 我们接触过STL中的部分容器&#xff0c;比如&#xff1a;vecto…...

BLIP2-图像文本预训练

文章目录摘要解决问题算法模型结构通过frozen图像编码器学习视觉语言表征图像文本对比学习&#xff08;ITC&#xff09;基于图像文本生成&#xff08;ITG&#xff09;图文匹配&#xff08;ITM&#xff09;从大规模语言模型学习视觉到语言生成模型预训练预训练数据预训练图像编码…...

Faster-Rcnn修改转数据集文件

目录 学习python的一些基础知识 argparser assert关键字 让你秒懂Python 类特殊方法__getitem__ lxml.etree.fromstring的使用 统计一下json文件内的种类 正脸红外光 正脸-混合红外光 正脸-交叉偏振光 正脸-平行偏振光 正脸-紫外光 正脸-棕色光 调用mydataset可视化…...

带你沉浸式体验删库跑路

前言:学习的过程比较枯燥,后面会记录一些比较有意思的东西&#xff0c;比如程序员之间流传的删库跑路的梗,当然本次测试是在虚拟机上进行的并进行了快照保护,所以其实没太大问题。首先得要有一个虚拟机要有一个linux iso文件装在虚拟机上以上两点不是本文重点,如果有需要可以私…...

Linux学习(8.5)文件内容查阅

目录 文件内容查阅&#xff1a; 直接检视文件内容 cat (concatenate) tac (反向列示) nl (添加行号列印) 可翻页检视 more (一页一页翻动) less (一页一页翻动) 数据撷取 tail (取出后面几行) 非纯文字档&#xff1a; od 修改文件时间或建置新档&#xff1a; touc…...

【Docker】命令总结

目录 1.镜像命令 1.1拉取镜像 1.2查看镜像 1.3保存镜像 1.4导入镜像 2.容器命令 2.1创建并运行容器 2.2删除容器 2.3进入容器 2.4查看容器状态 2.5暂停容器 2.6恢复容器 2.7停止容器 2.8启动容器 2.8查看容器日志 3.数据卷命令 3.1创建数据卷 3.2查看所有数据…...

并发编程-学习总结(上)

目录 1、线程基础 1.1、线程实现方法 1.2、如何正确停止线程 1.3、Java线程的六种状态 1.4、wait/notify/notifyAll注意事项 1.4.1、为什么 wait 、notify、notifyAll必须在 synchronized 保护的同步代码中使用&#xff1f; 1.4.2、为什么 wait/notify/notifyAll 被定义…...

QT之OpenGL混合

QT之OpenGL混合1. 概述2. 实现2.1 丢弃片段2.1.1 Demo2.2 混合2.2.1 相关函数2.2.2 排序问题2.2.3 Demo1. 概述 OpenGL中&#xff0c;混合(Blending)通常是实现物体透明度(Transparency)的一种技术。 2. 实现 2.1 丢弃片段 在某些情况下&#xff0c;有些片段是只需要设置显…...

【1255. 得分最高的单词集合】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 你将会得到一份单词表 words&#xff0c;一个字母表 letters &#xff08;可能会有重复字母&#xff09;&#xff0c;以及每个字母对应的得分情况表 score。 请你帮忙计算玩家在单词拼写游戏中所能获…...

nginx模块介绍

新编译前&#xff0c;在对应的nginx原编译文件夹 如&#xff1a;nginx-1.23.0 下&#xff0c;要 make clean 清空以前编译的objs文件夹&#xff0c;实际上就是执行了rm objs文件夹。 很多要用到git&#xff0c;先yum install git -y echo-nginx-module 让nginx直接使用echo的…...

排错工具ping和trace(电子科技大学TCP/IP实验四)

一&#xff0e;实验目的 1、了解网络连通性测试的方法和工作原理 2、了解网络路径跟踪的方法和工作原理 3、掌握 MTU 的概念和 IP 分片操作 4、掌握 IP 分组生存时间&#xff08;TTL&#xff09;的含义和作用 5、掌握路由表的作用和路由查找算法 二&#xff0e;预备知识 …...

node.js中ws模块创建服务端和客户端

一、WebSocket出现的原因 1、Http协议发布REST API 的不足&#xff1a; 每次请求响应完成之后&#xff0c;服务器与客户端之间的连接就断开了&#xff0c;如果客户端想要继续获取服务器的消息&#xff0c;必须再次向服务器发起请 求。这显然无法适应对实时通信有高要求的场景…...

kubernates-1.26.1 kubeadm containerd 单机部署

k8s1.26 kubeadm containerd 安装 kubeadm init 时提示 containerd 错误 failed to pull image “k8s.gcr.io/pause:3.6” 报错日志显示containerd pull时找不到对应的pause版本&#xff0c;而不是registry.k8s.io/pause:3.9 [rootk8s-master containerd]# kubeadm init --k…...

如何在 iPhone 上恢复已删除的通话记录/通话记录

您的通话记录/通话记录可能很重要&#xff0c;尤其是当您想要拨打之前联系过但未保存的号码时。如果您碰巧删除了通话记录&#xff08;有意或无意&#xff09;&#xff0c;本指南将帮助您了解如何检索它们并找回您需要使用的所有记录。我们将根据您的情况和您拥有的工具讨论不同…...

Canonical为所有支持的Ubuntu LTS系统发布了新的Linux内核更新

导读Canonical近日为所有支持的Ubuntu LTS系统发布了新的Linux内核更新&#xff0c;以解决总共19个安全漏洞。新的Ubuntu内核更新仅适用于长期支持的Ubuntu系统&#xff0c;包括Ubuntu 22.04 LTS&#xff08;Jammy Jellyfish&#xff09;、Ubuntu 20.04 LTS&#xff08;Focal F…...

MS9122是一款USB单芯片投屏器,内部集成了USB2 0 控制器和数据收发模块、HDMI 数据接口和音视频处理模块。MS9122可以通过USB接口显示

MS9122是一款USB单芯片投屏器&#xff0c;内部集成了USB2.0 控制器和数据收发模块、HDMI 数据接口和音视频处理模块。MS9122可以通过USB接口显示或者扩展PC、智能手机、平板电脑的显示信息到更大尺寸的显示设备&#xff0c;支持HDMI视频接口。 主要功能特征 HDMI v1.4兼容 最大…...

C++学习笔记-数据抽象

简单的说&#xff0c;数据抽象是用来描述数据结构的。数据抽象就是 ADT。一个 ADT 主要表现为它支持的一些操作&#xff0c;比方说 stack.push、stack.pop&#xff0c;这些操作应该具有明确的时间和空间复杂度。另外&#xff0c;一个 ADT 可以隐藏其实现细节&#xff0c;比方说…...

【Android】Android开发笔记(一)

【Android】Android开发笔记&#xff08;一&#xff09; 在Android Studio中import module和delete moduleimport moduledelete moduleAndroid Studio中App&#xff08;Module&#xff09;无法正常运行在实机上测试App一些基本概念App的工程结构结语在Android Studio中import m…...

C语言数据结构(二)—— 受限线性表 【栈(Stack)、队列(Queue)】

在数据结构逻辑层次上细分&#xff0c;线性表可分为一般线性表和受限线性表。一般线性表也就是我们通常所说的“线性表”&#xff0c;可以自由的删除或添加结点。受限线性表主要包括栈和队列&#xff0c;受限表示对结点的操作受限制。一般线性表详解&#xff0c;请参考文章&…...

线程安全之synchronized和volatile

目录 1.线程不安全的原因 2.synchronized和volatile 2.1 synchronized 2.1.1 synchornized的特性 2.1.2 synchronized使用示例 2.2 volatile 我们先来看一段代码&#xff1a; 分析以上代码&#xff0c;t1和t2这两个线程的任务都是分别将count这个变量自增5000次&#xff…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...