你是我的映射,我是你的值:C++ map 中的心灵共鸣

news2024/11/26 16:33:59

在这里插入图片描述

文章目录

  • map的概念
  • 一、map的使用
    • 1. 插入删除相关
      • 1)插入
        • (1) 插入语法
        • (1) 插入语法
      • 2)删除
  • 二. map的遍历
  • 三、map重载operator[]
  • 四、小试🐂🔪
    • 1. 前K个高频单词
    • 2. 单词识别
  • 总结


map的概念

map是key_value的模型:

一棵树,每个结点存一个pair
在这里插入图片描述

  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的使用

1. 插入删除相关

在这里插入图片描述

1)插入

(1) 插入语法

首先,map的插入也是默认去重的,因为map里存的是pair,所以插入操作我们必须要插入pair,一下是几种插入方式:

1.构造一个pair对象进行插入
在这里插入图片描述

  1. 插入一个pair的匿名对象
    在这里插入图片描述
  1. 对于c++98可以调用构造pair的函数,这个函数包含在pair中,他会调用构造函数返回一个pair的对象
    在这里插入图片描述
    在这里插入图片描述
  1. 对于c++11可以使用{ },c++11支持多参数构造函数的隐式类型转化
    这种转化方式是:(1)多参数隐式类型转化。
    (2)构造 + 拷贝构造 -> 直接构造
    在这里插入图片描述

一般来说我们喜欢用后两种~~~


(1) 插入语法

在这里插入图片描述
插入支持直接插入pair,也支持迭代器位置,和一段迭代区间。
这里我们重点看第一种:

首先:对于插入操作来说,如果遇到相同的key,不插入,也不覆盖,再插入过程之中,只比较key,与value无关。
在这里插入图片描述

然后,对于直接插入pair的insert返回值不是一个单纯的bool,而是一个pair:
pair<iterator, bool>

对于multimap来说,它就不默认去重了,可以插入key相等的元素


2)删除

删除很简单,根据key来删除就可以了

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


二. map的遍历

因为map的值是pair,因此使用迭代器遍历map,直接*it得到的是pair,而pair没有重载流插入,流输出。
因此,不能cout << *it << " "; ++it

这里提供两种遍历的方式,首先我们看pair,里面包含了两个值,其中第一个是first,第二个是second。因此:

  1. 使用迭代器遍历

我们用*it获取pair,再用first()与second()获取pair中的元素
在这里插入图片描述
也支持范围for:
在这里插入图片描述

  1. 使用->进行遍历
    迭代器出来的是it是一个指针,这里pair重载了->,it->返回的是对应pair的指针,因此实际上访问时(it->)->,但这里编译器进行了优化,因此直接用箭头就可以访问first和second

在这里插入图片描述

在这里插入图片描述


三、map重载operator[]

map中的[ ]是根据key来返回value。

假设我们要统计数组中,水果出现的次数:
如果没有重载[ ],那么我们只能这样写。
在这里插入图片描述

如果重载了[ ],就不一样了,通过[key]找value:
在这里插入图片描述
但是这里面有一个问题,就是如果这个当第一次出现的时候是怎么初始化的?

因此我们就要研究 operator[]的返回值了。
查阅文档我们可以发现 operator[]返回的是这样一串东西:
在这里插入图片描述

把他拆分出来看就是返回

  1. 调用insert的返回值的是一个pair
  2. pair取出first是->iterator
  3. *iterator就是对应map中的pair
  4. 再取出这个pair中的second就是key对应的value

因此我们就要研究insert的返回值了:

前文提到:对于直接插入pair的insert返回值不是一个单纯的bool,而是一个pair:pair<iterator, bool>
这个pair的first是map中对应的插入值的迭代器,second来判断插入成功还是失败。

在这里插入图片描述
这里分两种情况:
在这里插入图片描述

在这里插入图片描述

因此相当于operator的返回值是这样的:
在传参传insert的pair的second时,传的是一个缺省值V(),如果存在了,就用已经存在的val,如果不存在就用缺省构造出来的value,int类型就是0,string类型就是nullptr等等…
在这里插入图片描述

综上,这里operator[ ]可以用key来找到value~


四、小试🐂🔪

1. 前K个高频单词

前K个高频单词
在这里插入图片描述

/*
思路:经典的top-k问题
  1. 先采用map统计出每个单词出现的次数
  2. 采用优先级队列,借助map中的前k个元素创建一个小堆,剩余元素向堆中插入一个删除一个,使用保持堆中有k个元素,直到将map中的元素插入完
  3. 堆中剩余的元素就是出现次数最多的k个元素,只不过是次数从小到达的,
     将堆中的元素逐次放置到vector中,注意只放字符串,然后逆置
*/

class Solution {
    // 比较器
    // 因为放入优先级队列的元素为:单词与其出现次数构成的键值对,优先级队列不能直接比较,因此
    // 需要提供一个比较器,在实例化用该比较器实例化
    // 比较方式:
    // 按照次数比较,如果次数相同,再按照单词字典熟序比较
    struct Com{
        bool operator()(pair<string,int> &a,const pair<string,int> &b)
        {
            if(a.second!=b.second)
            {
               return a.second>b.second;
            }
            else
            {
               return a.first<b.first;
            }
        }
    };

public:
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        // 采用map统计每个单词出现的次数
        map<string, int> m;
        for(auto e : words)
            m[e]++;
        
        // 采用优先级队列,找出现次数最多的前K个IP地址
        priority_queue<pair<string, int>, vector<pair<string, int>>, Com> q;

        // 用map中的元素插入到优先级队列中,当优先级队列中的元素等于k个时,插入一个,删一个
        // 始终保证优先级队列中有k个元素
        for(auto e : m)
        {
            q.push(e);
            if(q.size() > k)
                q.pop();
        }

        // 将优先级队列中元素(键值对)中的字符串部分放置到vector中
        vector<string> ret;
        while(!q.empty())
        {
            ret.push_back(q.top().first);
            q.pop();
        }

        // 因为是根据次数创建的小堆,因此需要逆置
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

2. 单词识别

单词识别
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;
#include <string>
#include <map>
#include <set>



typedef pair<string, int> Word;
class Compare {
  public:
    bool operator()(const Word& left, const Word& right)const {
        // 次数从大到小排序
        // 如果次数相同,再按照单词字典序排序
        return (left.second > right.second) || 
               (left.second == right.second && left.first < right.first);
    }
};



int main() {
    string s;
    while (getline(cin, s)) {
        map<string, int> m;
        string temp;


        // 分割单词,采用map统计每个单词出现的次数
        for (size_t i = 0; i < s.size(); ++i) {
            if (s[i] == ' ' || s[i] == ',' || s[i] == '.') {
                // 一个单词解析结束
                if (temp != "")
                    m[temp]++;


                temp = "";
            } else {
                // 注意:题目已说明不区分大小写,那么A和a算是一个单词,故需要将大小写统一
                temp += tolower(s[i]);
            }
        }


        // 将map中的<单词,次数>放到set中,并按照次数升序,次数相同按照字典序规则排序
        set<Word, Compare> s(m.begin(), m.end());
        
        // 将本次统计到的结果按照要求输出
        for (auto& e : s)
            cout << e.first << ":" << e.second << endl;
        cout << endl;
    }
    return 0;
}

总结

到这里,map与set就结束啦,map与set为后面红黑树与AVL树的学习打下了基础!!!是很重要的数据结构。

创作不易,如果本片文章对各位有帮助的话,求求各位大佬一个一键三连,谢谢大家🤩🤩🤩

在这里插入图片描述

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

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

相关文章

RabbitMQ客户端应用开发实战

这一章节我们将快速完成RabbitMQ客户端基础功能的开发实战。 一、回顾RabbitMQ基础概念 这个RabbitMQ的核心组件&#xff0c;是进行应用开发的基础。 二、RabbitMQ基础编程模型 RabbitMQ提供了很多种主流编程语言的客户端支持。这里我们只分析Java语言的客户端。 上一章节提…

RNA-seq 差异分析的点点滴滴(1)

引言 本系列[1])将开展全新的转录组分析专栏&#xff0c;主要针对使用DESeq2时可能出现的问题和方法进行展开。 为何使用未经标准化的计数数据&#xff1f; DESeq2 工具包在接收输入时&#xff0c;期望得到的是未经处理的原始计数数据&#xff0c;比如从 RNA-seq 或其他高通量测…

RTC精度及校准

RTC精度偏差&#xff1a; RTC的基准时间和精度与石英晶体的频率相关&#xff0c;晶体的谐振频率取决于温度&#xff0c;因此RTC性能与温度相关&#xff0c;晶体的频率偏差是晶体正常频率的温度反转函数。 一、硬件方面&#xff1a; 1.使用高精度振荡器的RTC模块&#xff1b; …

智慧城市路面垃圾识别系统产品介绍方案

方案介绍 智慧城市中的路面垃圾识别算法通常基于深度学习框架&#xff0c;这些算法因其在速度和精度上的优势而被广泛采用。这些模型能够通过训练识别多种类型的垃圾&#xff0c;包括塑料袋、纸屑、玻璃瓶等。系统通过训练深度学习模型&#xff0c;使其能够识别并定位多种类型…

【安当产品应用案例100集】029-使用安全芯片保护设备核心业务逻辑

我国工业企业普遍缺乏数据安全意识&#xff0c;对数据安全保护缺乏基本认识。这导致企业在数据安全方面的投入不足&#xff0c;保护能力基本不具备&#xff0c;难以有效应对数据安全风险。不过随着安全事件越来越多&#xff0c;很多工业企业的安全意识也越来越高&#xff0c;在…

遥控器工作核心技术以及传输信号算法详解!

一、遥控器传输信号算法 无线通信技术&#xff1a;无人机遥控器信号传输算法主要基于无线通信技术&#xff0c;通过特定的调制、编码和信号处理技术&#xff0c;将遥控器的操作指令转化为无线电信号&#xff0c;并传输给被控制设备。被控制设备接收到信号后&#xff0c;再将其…

性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台

前言 在当前激烈的市场竞争中&#xff0c;创新和效率成为企业发展的核心要素之一。在这种背景下&#xff0c;如何保证产品和服务的稳定性、可靠性以及高效性就显得尤为重要。 而在软件开发过程中&#xff0c;性能测试是一项不可或缺的环节&#xff0c;它可以有效的评估一个系…

电力调度控制台安全性有没有保障

电力调度控制台作为电力系统的核心组成部分&#xff0c;承担着监控、控制和调度电网运行的重要任务。随着电力系统的不断发展和智能化水平的提升&#xff0c;电力调度控制台的安全性问题也日益受到关注。那么&#xff0c;电力调度控制台的安全性究竟有没有保障呢? 从技术层面来…

练习LabVIEW第四十四题

学习目标&#xff1a; 计算学生三门课(语文&#xff0c;数学&#xff0c;英语)的平均分&#xff0c;并根据平均分划分成绩等级。要求输出等级A,B,C,D,E。90分以上为A&#xff0c;80&#xff5e;89为B&#xff0c;70&#xff5e;79为C&#xff0c;60&#xff5e;69为D&#xff…

录音怎么转换成文字?这5款视频语音转文字工具轻松搞定!

在各类会议、讲座、采访及日常学习活动中&#xff0c;录音已成为我们记录关键信息的常用手段。然而&#xff0c;面对那些可能长达数小时甚至更久的录音文件&#xff0c;如何快速有效地将它们转换成可编辑、可搜索的文字资料&#xff0c;确实是一个令人困扰的问题。为此&#xf…

蓝桥杯c++算法学习【1】之枚举与模拟(卡片、回文日期、赢球票:::非常典型的比刷例题!!!)

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 枚举与模拟 一、卡片&#xff1a; 【问题描述】 …

面试题:Spring(一)

1. Spring框架中bean是单例么&#xff1f; Service Scope("singleton") public class UserServiceImpl implements UserService { }singleton : bean在每个Spring IOC容器中只有一个实例。prototype&#xff1a;一个bean的定义可以有多个实例。 2. Spring框架中的…

InnoDB 存储引擎<七>通用表空间+临时表空间

目录 通⽤表空间 - General Tablespace 临时表空间 - Temporary Tablespaces 通⽤表空间 - General Tablespace 对应磁盘上的文件需要用户手动创建 1.通⽤表空间的作⽤和特性&#xff1f; 解答问题&#xff1a; 1.作用&#xff1a;可以把数据量比较小且强相关的表&#xff…

linux 通过apt安装软件包时出现依赖包版本不对的问题解决

通过网上查找解决办法时&#xff0c;发现的解决办法无法完美解决问题: 比如通过安装对应版本解决 如: sudo apt-get install xxx2.7.0ubuntu 这样会先卸载原先包&#xff0c;在安装对应版本的包 或者直接删除依赖的包 sudo apt-get purge xxxx 如果碰到底层包的话&#xf…

用示例来看C2Rust工具的使用和功能介绍

C2Rust可以将C语言的源代码转换成Rust语言的源代码。下面是一个简单的C语言代码示例,以及使用c2Rust工具将其转换为Rust安全代码的过程。 C语言源代码示例 // example.c #include <stdio.h>int add(int a, int b)

提升电机控制的关键:东芝TB6605FTG深度解析

在电机控制领域&#xff0c;对高效、精确且可靠的组件的需求是不可忽视的。东芝的TB6605FTG正是一款具备这些特性的电机驱动IC&#xff0c;是工程师们在设计电机控制系统时的理想选择。 主要特性与规格 TB6605FTG的核心是一个三相全波电机驱动IC&#xff0c;专为无刷直流电机控…

动态规划理论基础和习题【力扣】【算法学习day.25】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

【K8S系列】K8S 集群 CPU 爆满导致 Pod Pending 状态的分析与解决方案

在 Kubernetes 集群中&#xff0c;CPU 突然爆满可能导致 Pod 状态变为 Pending&#xff0c;影响应用的可用性。本文将深入分析其原因&#xff0c;并附上相关命令及其执行结果&#xff0c;帮助你更好地理解和解决此问题。 1. 问题描述 在 Kubernetes 集群中&#xff0c;当 CPU …

开源代码管理平台Gitlab如何本地化部署并实现公网环境远程访问私有仓库

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 本文主要介绍如何在Linux CentOS8 中搭建GitLab私有仓库并且结合内网穿透工具实现在公网…

Linux磁盘存储

磁盘存储 设备文件 设备文件是类Unix操作系统&#xff08;包括Linux&#xff09;中一种特殊的文件类型&#xff0c;它代表了设备接口&#xff0c;使得用户空间的程序可以通过标准的文件操作来访问和控制硬件设备。设备文件为周边设备提供了简单的接口&#xff0c;如打印机、硬…