【C++】map和set的使用

在这里插入图片描述

🚀write in front🚀
📜所属专栏: C++学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 1. 关联式容器
  • 2. 键值对
  • 3. 树形结构的关联式容器
    • 3.1`set`:
      • 3.1.1:set的介绍:
      • 3.1.2set几个常用函数:
        • a.count函数:
        • b.find函数:
        • c.边界处理的函数:
          • lower_bound和upper_bound:
        • equal_range:
      • 3.1.3set的使用:
    • 3.2`multiset`:
    • 3.3`map`:
      • 3.3.1map的介绍:
      • 3.3.2map的常用函数:
        • a.insert函数:
        • b.map的遍历:
        • c.[]访问:
      • 3.3.3map的使用:
    • 3.4multimap:
  • 一道经典例题:
    • 方法1:
    • 方法2:
    • 方法3(不推荐):

1. 关联式容器

  在初阶阶段,我们已经接触过STL中的部分容器,比如:list,vector,deque,forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身

  那什么是关联式容器?它与序列式容器有什么区别?
  关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,并且在数据检索时比序列式容器效率更高(实现是AVL树,就是进阶版的二叉搜索树)。

2. 键值对

  用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};

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

  根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:mapsetmultimap,multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列(都是中序遍历)。下面一依次介绍每一个容器。

3.1set

3.1.1:set的介绍:

  1. set是按照一定次序存储元素的容器

  2. set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
    在这里插入图片描述

  3. set在底层是用二叉搜索树(红黑树)实现的。

  4. map不同,map中存储的是真正的键值对<key, value>set中只放value,但在底层实际存放的是<value, value>构成的键值对。

  5. set中插入元素时,只需要插入value即可,不需要构造键值对。

  6. set中的元素不可以重复(因此可以使用set进行去重)。

  7. 使用set的迭代器遍历set中的元素,可以得到有序序列

  8. set中的元素默认按照小于来比较:less<T>
    在这里插入图片描述

  9. set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n

3.1.2set几个常用函数:

  和其他容器一样,set的迭代器,构造函数,析构函数,容量,插入删除等函数可以自己去查看文档了,在这里我就讲几个常用和易错的几个函数:

a.count函数:

在这里插入图片描述
  此函数就是返回val值在set里面有多少个。但是因为set里面的元素不重复,所以这个函数在set里面只可能返回0或1,所以我们查找元素在不在的时候可以使用这个函数。

b.find函数:

在这里插入图片描述
  其实这个函数也很简单,我们只需要注意一下他的返回值:

  • 找到了就返回那个地方的迭代器
  • 没找到就返回末尾的迭代器end()
c.边界处理的函数:
lower_bound和upper_bound:

说白了,这两个函数就是为了erase()服务的:他们可以给erase提供一个范围空间,供其删除中间的内容。
在这里插入图片描述
在这里插入图片描述
由于erase删除的时候是左闭右开的原则,这两个函数根据这个原则,lower_bound返回的值是>=val的,而upper_bound返回的值是>val的(都是为了左开右闭准备的)
举个🌰:

multiset<int> s;for (int i = 1; i < 10; i++){s.insert(i * 10);//10 20 30 40 50 60 70 80 90}auto itlow = s.lower_bound(30);//30auto itup = s.upper_bound(60);//70cout << *itlow << endl;cout << *itup << endl;s.erase(itlow,itup);//左闭右开,删除了30,40,50,60
equal_range:

在这里插入图片描述
  说白了,这个函数也是应该使用在multiset里面更好,他是返回val值的一小段区间,其实也是为了erase这个val值。他返回的这个值是一个pair,第一个其实就相当于lower__bound,第二个就相当于upper__bound

auto ret = s.equal_range(30);//该函数返回的是一个pair,因为也要左闭右开,所以还是和什么一样,而pair的first是lower,second是upperauto itlow = ret.first;//>=  这里相当于lower_boundauto itup = ret.second;//>	 这里相当于upper_boundcout << *itlow << endl;//cout << *itup << endl;s.erase(itlow,itup);//左闭右开

3.1.3set的使用:

  set可以进行去重,或者检查有没有重复的元素,比如我们之前做的判断链表是否为环形链表的题,如果我们将链表的结点都存入set,如果发现一样的,那就一定是环形链表了。(判断记得用count()更简单)

3.2multiset

其实有两个函数就是为multiset写的:
在这里插入图片描述
还要就是在删除erase(val)或通过equal_range()删除val的时候,会将val值全部删掉!!

3.3map

3.3.1map的介绍:

  1. 在map中,键值key通常用于排序和唯一的标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
    value_type绑定在一起,为其取别名称为pair:typedef pair<const key, T> value_type;
  2. 在内部,map中的元素总是按照键值key进行比较排序的。
  3. map支持下标访问符加粗样式,即在[]中放入key,就可以找到与key对应的value
  4. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树)
  5. key的值不能改,value的值可以改:
typedef pair<const key, T> value_type;

3.3.2map的常用函数:

a.insert函数:

对于pair类型,我们该怎么插入呢?有下面几种方法:

map<string, string> mp;//c++98!!//方法一:构造后插入pair<string, string> k1("insert", "插入");mp.insert(k1);//方法二:匿名对象插入mp.insert(pair<string, string> ("sort", "排序"));//方法三:调用make_pair函数mp.insert(make_pair("string", "字符串"));//c++11:支持了多参数的构造函数隐式类型转换!!mp.insert({ "map","映射" });
b.map的遍历:

那么,我们的map如何遍历呢?
其实还是和其他的容器一样,只是我们的map里面是pair类型,要多一次解引用:

auto it = mp.begin();while (it != mp.end()){(*it).second = "xxx";//(*it).first = "xxx";只能修改第二个值,不能修改第一个值cout << (*it).first << " :" << (*it).second << endl;it++;}cout << endl;while (it != mp.end()){cout << it->first << " :" << it->second << endl;//这里本来应该是it->->first原本是://pair<K,V> operator->()//{//return &it->val;//}it++;}for (const auto& kv : mp){//kv.second = "ccc";cout << kv.first << " :" << kv.second << endl;}
c.[]访问:

如果要通过map来统计次数该如何统计呢?
通常大家会这样统计:

string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> mp;for (auto& ch : arr){auto it=mp.find(ch);if (it == mp.end()){mp.insert({ ch,1 });}else{it->second++;}}

但是还要更简便的方法,那就是使用[]。我们先来看看他的使用:
在这里插入图片描述
实际上这里的源码是这样的:
在这里插入图片描述
这里就不得不说insert的返回值了:
在这里插入图片描述
所以上面[]的实现简化下来是这样的:
在这里插入图片描述
所以上面的统计次数可以这样来写:

string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> mp;
for (auto& ch : arr){mp[ch]++;}

这样的话,我们就可以通过key来插入/修改value的值了,是不是很方便呢?

3.3.3map的使用:

map其实就是一种映射关系,以后只要见到有映射关系的题目都可以通过map来实现:
比如之前的括号的题目:
在这里插入图片描述
还有随机链表复制的题目。

3.4multimap:

multimap和multiset类似,就是可以存入相同的key的值。

一道经典例题:

前k个高频单词
在这里插入图片描述
在学习了map之后,我们就可以通过map进行计数,而且而且!map还顺便排了个序!!虽然不是最终结果,但是还是给我们省了很多步骤。下面有三种方法解决这个问题:

方法1:

先用map统计次数,而且此时也正好按字典序排序了,但是要按次序排序,而我们map不能通过算法里面的排序(快排是用数组的),所以我们用vector来保存pair。但是最后在快排的时候,快排没有稳定性相对位置会改变),所以我们用另外一个排序,叫stable_sort来排序。

class Solution {
public:struct Greater{bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2){return kv1.second > kv2.second;}};vector<string> topKFrequent(vector<string>& words, int k){map<string, int> countmap;for (const auto& ch : words){countmap[ch]++;}vector<string> v;vector<pair<string, int>>kv(countmap.begin(), countmap.end());stable_sort(kv.begin(), kv.end(), Greater());for (int i = 0; i < k; i++){v.push_back(kv[i].first);}return v;}
};

方法2:

其实,我们还可以通过对仿函数进行限制,还是可以使用sort函数排序的。此时仿函数的限制就非常的巧妙!!在次数相等的时候让其通过字典序来比!!

class Solution {
public:struct Greater{bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2){return kv1.second > kv2.second || kv1.second == kv2.second && kv1.first < kv2.first;}};vector<string> topKFrequent(vector<string>& words, int k){map<string, int> countmap;for (const auto& ch : words){countmap[ch]++;}vector<string> v;vector<pair<string, int>>kv(countmap.begin(), countmap.end());sort(kv.begin(), kv.end(), Greater());for (int i = 0; i < k; i++){v.push_back(kv[i].first);}return v;}
};

方法3(不推荐):

multimap在构建的时候,在排序有可能是稳定的(这个看编译器,其他编译器不一定对)。所以如果multimap稳定的情况下,我们就可以在创建一个multimap,来通过次数再来排一次序!


class Solution {
public:struct Greater{bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2){return kv1.second > kv2.second || kv1.second == kv2.second && kv1.first < kv2.first;}};vector<string> topKFrequent(vector<string>& words, int k){map<string, int> countmap;for (const auto& ch : words){countmap[ch]++;}multimap<int, string, greater<int>> sortMap;for (const auto& e : countmap){sortMap.insert({ e.second,e.first });}vector<string> v;auto it = sortMap.begin();while (k--){v.push_back(it->second);++it;}return v;}
};

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
C语言学习
算法
智力题
初阶数据结构
Linux学习
C++学习
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

斯坦福数据挖掘教程·第三版》读书笔记(英文版)Chapter 10 Mining Social-Network Graphs

来源&#xff1a;《斯坦福数据挖掘教程第三版》对应的公开英文书和PPT。 Chapter 10 Mining Social-Network Graphs The essential characteristics of a social network are: There is a collection of entities that participate in the network. Typically, these entiti…

JS defineProperty详解

defineProperty Object.defineProperty():方法会在对象上直接定义个新的属性&#xff0c;或者修改现有的属性&#xff0c;并返回此对象 let obj {} //与我们使用 obj.name zhangsna 效果一样 但是用defineProperty定义的属性无法改变 或者删除 Object.defineProperty(obj,n…

MEIS —— 前端部分基本配置

项目基本配置 这篇文章我们随着上一篇文章继续往下叙述&#xff0c;主要是将element和windicss等开发配置进项目中&#xff0c;以及基本的一些页面和组件给他完成。 1. 安装element plus 运行&#xff1a; npm install element-plus --save 这里我们是按需引入(自动)&#x…

flink处理函数--副输出功能

背景 在flink中&#xff0c;如果你想要访问记录的处理时间或者事件时间&#xff0c;注册定时器&#xff0c;或者是将记录输出到多个输出流中&#xff0c;你都需要处理函数的帮助&#xff0c;本文就来通过一个例子来讲解下副输出 副输出 本文还是基于streaming-with-flink这本…

基于YOLOv8的安全帽检测系统

1.Yolov8介绍 Ultralytics YOLOv8是Ultralytics公司开发的YOLO目标检测和图像分割模型的最新版本。YOLOv8是一种尖端的、最先进的&#xff08;SOTA&#xff09;模型&#xff0c;它建立在先前YOLO成功基础上&#xff0c;并引入了新功能和改进&#xff0c;以进一步提升性能和灵活…

树的表示——孩子兄弟表示法

从图中可以看出&#xff0c;树的每个结点&#xff0c;都有不确定的指向他们的孩子的节点&#xff0c;如果我们定义这样一个结构体来便是数的结构的话&#xff1a; struct TreeNode { int val; struct TreeNodep1; struct TreeNodep1; … }; 是不能够表示一棵树的&#xff0c;因…

9.25 day 2

1. 简述方法重写与方法重载的意义与区别&#xff1a; 方法重写&#xff1a; 1.参数列表必须完全与被重写方法相同 //参数列表&#xff08;分为四种&#xff09;&#xff1a; &#xff08;1&#xff09;无参无返回值方法&#xff1b; &#xff08;2&#xff09;有参无返回…

“智慧时代的引领者:探索人工智能的无限可能性“

目录 一.背景 二.应用 2.1金融领域 2.2医疗领域 2.3教育领域 三.发展 四.总结: 一.背景 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;&#xff0c;是指通过计算机程序模拟人类智能的一种技术。它是计算机科学、工程学、语言学、哲学等多…

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构&#xff0c;分别为&#xff1a;string&#xff08;字符串&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、hash&#xff08;哈希&a…

CUDA、cudNN 、CUDAToolKit三者关系

cudatoolkit和cuda有关系吗 CUDA 是 NVIDIA 推出的一种并行计算平台和编程模型&#xff0c;可以在 NVIDIA GPU 上运行 C/C 代码。 CUDA Toolkit 是 NVIDIA 提供的一套开发工具&#xff0c;它包含了用于开发 CUDA 应用程序所需的各种工具&#xff0c;如编译器、调试器和库。 因…

音频编辑软件Steinberg SpectraLayers Pro mac中文软件介绍

Steinberg SpectraLayers Pro mac是一款专业的音频编辑软件&#xff0c;旨在帮助音频专业人士进行精细的音频编辑和声音处理。它提供了强大的频谱编辑功能&#xff0c;可以对音频文件进行深入的频谱分析和编辑。 Steinberg SpectraLayers Pro mac软件特点 1. 频谱编辑&#xff…

transformers简介

目录 1、前言 2、网络结构 &#xff08;1&#xff09;、Transformers的总体架构可以分为四部分 &#xff08;2&#xff09;、输入文本包含 &#xff08;3&#xff09;、输出部分包含 &#xff08;4&#xff09;、编码器部分 &#xff08;5&#xff09;、解码器部分 1、前…

sci投稿流程(从投稿到录用全流程解析)

论文投稿流程 1.初稿:准备好论文&#xff0c;给编辑的信(cover letter&#xff09; 2.返修: 一.会返回两个东西: 1&#xff09;编辑的决定 (小修minior review&#xff0c;大修major review&#xff0c;拒稿reject等等)。只要不是审稿人质疑创新性问题和数据造假问题&…

Mybatis配置文件(mybatis-config.xml)和Mapper映射文件(XXXMapper.xml)模板

配置文件 ${dirver} ---> com.mysql.jdbc.Driver ${url} ---> jdbc:mysql://localhost:3306/数据库名 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""h…

SpringBoot 如何解决跨域问题

Spring Boot 中的跨域请求&#xff08;Cross-Origin Request&#xff09;问题与解决方案 跨域请求是指浏览器从一个域名的网页去请求另一个域名的资源&#xff0c;它是为了增强 Web 安全性而产生的限制。Spring Boot 应用程序通常会面临跨域请求的问题&#xff0c;本文将介绍跨…

c++ 关键字和标识符

在本教程中&#xff0c;我们将学习关键字&#xff08;C 编程中的保留关键字&#xff0c;它们是语法的一部分&#xff09;。另外&#xff0c;我们还将学习标识符以及如何命名它们。 C 关键字 关键字是预定义的单词&#xff0c;对编译器具有特殊的含义。例如&#xff0c; 示例…

AWS SAA知识点整理(作成中)

共通 一些信息已经更新了&#xff0c;但参考题的答案还是旧的。 比如&#xff1a; S3的最大读写性能已经提高到 3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second 并且不再要求使用random prefix 题目中有时候会让选择Not violation 不合适的一项&#xff…

2022年6月和7月的工作经历

6月 3D打标软件 3D打标软件&#xff0c;要求在Open3d上加几个2D文字。大致有如下几个方案&#xff1a; 依葫芦画瓢&#xff0c;但O3DVisualizer派生于gui::Window&#xff0c;我的程序派生于Visualizer。工作量不小。 利用OpenGL输出文字&#xff0c;Baidu的两种方法一个编…

AI编程助手 Amazon CodeWhisperer 全面解析与实践

目录 引言Amazon CodeWhisperer简介智能编程助手智能代码建议代码自动补全 提升代码质量代码质量提升安全性检测 支持多平台多语言 用户体验和系统兼容性用户体验文档和学习资源个性化体验系统兼容性 功能全面性和代码质量功能全面性代码生成质量和代码安全性 CodeWhisperer的代…