【C++ STL有序关联容器】map 映射

news2025/1/16 5:54:07

文章目录

  • 【 1. 基本原理 】
  • 【 2. map 的创建 】
    • 2.1 调用默认构造函数,创建一个空的 map
    • 2.2 map 被构造的同时初始化
    • 2.3 通过一个 queue 初始化另一个 queue
    • 2.4 取已建 map 中指定区域内的键值对,初始化新的 map
    • 2.5 指定排序规则
  • 【 2. map 元素的操作 】
    • 实例 - 查找键
    • 实例 - map 某个键对应的值自加1
  • 【 3 map 支持的成员方法 】
    • 实例 - 输出map元素数量以及各个键值对

【 1. 基本原理 】

  • map 容器存储的都是 pair 对象,用 pair 类模板创建的键值对,即 pair<const K, T> 类型(其中 K 和 T 分别表示键和值的数据类型)的键值对元素。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、char、double 等)、使用结构体或类自定义的类型。通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。
  • 与此同时,在使用 map 容器存储多个键值对时, map容器会自动根据各键值对中键的大小,按照既定的规则进行 自动排序。默认情况下,map 容器选用 std::less<T>排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值 默认做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater<T>),也可以自定义排序规则。
  • map 容器中存储的各个键值对 不仅键独一无二,键的类型也会用 const 修饰,这意味着使用 map 容器存储的各个键值对, 键 既不能重复也不能被修改

【 2. map 的创建 】

  • map 容器定义在 <map> 头文件 中,并位于 std 命名空间 中。
  • map 容器的模板定义如下:
    • map 容器模板有 4 个参数,其中后 2 个参数都设有默认值。大多数场景中,我们只需要设定前 2 个参数的值,有些场景可能会用到第 3 个参数,但最后一个参数几乎不会用到。
template < class Key,                                     // 指定键(key)的类型
           class T,                                       // 指定值(value)的类型
           class Compare = less<Key>,                     // 指定排序规则
           class Alloc = allocator<pair<const Key,T> >    // 指定分配器对象的类型
           > class map;

2.1 调用默认构造函数,创建一个空的 map

  • 通过此方式创建出的 myMap 容器,初始状态下是空的,即没有存储任何键值对。鉴于空 map 容器可以根据需要随时添加新的键值对,因此创建空 map 容器是比较常用的。
map<string, int>myMap;

2.2 map 被构造的同时初始化

  • 在创建 map 容器的同时,也可以进行初始化,比如:
    由此,myMap 容器在初始状态下,就包含有 2 个键值对。
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
  • 再次强调,map 容器中存储的键值对,其本质都是 pair 类模板创建的 pair 对象。因此,下面程序也可以创建出一模一样的 myMap 容器:
map<string, int>myMap{make_pair("C语言程",10),make_pair("STL教程",20)};

2.3 通过一个 queue 初始化另一个 queue

  • 在某些场景中,可以利用先前已创建好的 map 容器,再创建一个新的 map 容器。 无论是调用复制构造函数还是调用拷贝构造函数,前提是需要保证两个容器的类型一致
  • 通过调用 map 容器的 拷贝构造函数,即可成功创建一个和 myMap 完全一样的 newMap 容器。
map<string, int>newMap(myMap);
  • C++ 11 标准中,还为 map 容器增添了 移动构造函数。当有临时的 map 对象作为参数,传递给要初始化的 map 容器时,此时就会调用移动构造函数。举个例子:
#创建一个会返回临时 map 对象的函数
map<string,int> disMap() 
{
    map<string, int>tempMap{ {"C语言教程",10},{"STL教程",20} };
    return tempMap;
}
//调用 map 类模板的移动构造函数创建 newMap 容器
map<string, int>newMap(disMap());

2.4 取已建 map 中指定区域内的键值对,初始化新的 map

  • map 类模板还支持取已建 map 容器中指定区域内的键值对,创建并初始化新的 map 容器。例如:
    这里,通过调用 map 容器的双向迭代器,实现了在创建 newMap 容器的同时,将其初始化为包含一个 {“STL教程”,20} 键值对的容器。
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
map<string, int>newMap(++myMap.begin(), myMap.end());

2.5 指定排序规则

  • 在以上几种创建 map 容器的基础上,我们都可以手动修改 map 容器的排序规则。
  • 默认情况下,map 容器调用 std::less<T> 规则,根据容器内各键值对的键的大小,对所有键值对 默认做升序排序
    因此,如下 2 行创建 map 容器的方式,其实是等价的:
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
map<string, int, less<string> >myMap{ {"C语言教程",10},{"STL教程",20} };

以上 2 种创建方式生成的 myMap 容器,其内部键值对排列的顺序为:
<“C语言教程”, 10>
<“STL教程”, 20>

  • 下面程序手动修改了 myMap 容器的排序规则,令其 指定做降序排序
map<string, int, greater<string> >myMap{ {"C语言教程",10},{"STL教程",20} };

此时,myMap 容器内部键值对排列的顺序为:
<“STL教程”, 20>
<“C语言教程”, 10>

【 2. map 元素的操作 】

  • 通过指定 键 的方式 访问键值对
    如果 该键存在,则返回该键对应的值;否则返回0。
myMap[ 要查找的键 ] 
  • 通过迭代器的方式访问键值对
    t->first为该迭代器对应的键,t->second为该迭代器对应的值。
auto t = myMap.begin();
cout <<  t->first << t->second << endl;//t->first为键,t->second为值

实例 - 查找键

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<string,int>myMap;
    myMap.emplace("Nami", 98);
    myMap.emplace("Luffy", 99);
    myMap.emplace("Soro", 97);
    
    cout <<  myMap["Nami"] << endl;//存在键相应的键值对,返回对应的值
    cout << myMap["Sanj"] << endl; //没有键对应的键值对,返回0

    auto t = myMap.begin();
    cout <<  t->first << t->second << endl;//t->first为键,t->second为值

    return 0;
}

在这里插入图片描述

实例 - map 某个键对应的值自加1

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<string,int>myMap;
    myMap.emplace("Nami", 1);

    myMap["Nami"]++;
    cout <<  myMap["Nami"] << endl;

    auto t = myMap.begin();
    t->second = t->second + 1;
    cout << t->second << endl;

    return 0;
}

在这里插入图片描述

【 3 map 支持的成员方法 】

map支持的成员方法功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(key)返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。
empty()若容器为空,则返回 true;否则 false。
size()返回当前 map 容器中存有键值对的个数。
max_size()返回 map 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[]map容器重载了 [] 运算符,只要知道 map 容器中某个键值对的键的值,就可以向获取数组中元素那样,通过键直接获取对应的值。
at(key)找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。
insert()向 map 容器中插入键值对。
erase()删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。
swap()交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。
clear()清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。
emplace()在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
count(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1

实例 - 输出map元素数量以及各个键值对

  • 创建 1个 map,输出map元素数量,最后输出各个键值对。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    //创建空 map 容器,默认根据个键值对中键的值,对键值对做降序排序
    map<string, string,greater<string>>myMap;
    //调用 emplace() 方法,直接向 myMap 容器中指定位置构造新键值对
    myMap.emplace("C语言教程", "http://c.biancheng.net/c/");
    myMap.emplace("Python教程", "http://c.biancheng.net/python/");
    myMap.emplace("STL教程", "http://c.biancheng.net/stl/");
    //输出当前 myMap 容器存储键值对的个数
    cout << "myMap size==" << myMap.size() << endl;
    //输出键值对
    if (!myMap.empty()) //判断当前 myMap 容器是否为空
    {
        //借助 myMap 容器迭代器,将该容器的键值对逐个输出
        for (auto i = myMap.begin(); i != myMap.end(); ++i)
            cout << i->first << " " << i->second << endl;
    }
    return 0;
}

在这里插入图片描述

  • 统计字符串中各字母字符对应的个数
#include <iostream>
#include<map>
using namespace std;
int main() {
    char str[100] = { 0 };
    cin.getline(str, sizeof(str));
    map<char, int>maps;
    for (int i = 0; str[i] != '\0'; i++) 
    {
        if (isalpha(str[i]))//判断是否是字符
            maps[str[i]]++;//maps[str[i]]++指的是取出map对应key的value值再累加,如果没有对应的键则会自动加入map中   

    }
    for (auto it = maps.begin(); it != maps.end(); it++)
    {
        cout << it->first << ":" << it->second << endl;
    }
    return 0;
}

在这里插入图片描述

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

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

相关文章

知识融合:知识图谱构建的关键技术

目录 一、引言二、知识图谱基础2.1 知识表示三元组属性图 2.2 知识抽取实体抽取关系抽取属性抽取 三、知识融合的核心问题3.1 实体识别与链接实体识别实体链接 3.2 重复实体合并方法示例 3.3 关系融合挑战方法示例 四、知识融合技术深度解析4.1 基于规则的方法规则设计原则规则…

噪声的力量:重新定义 RAG 系统的检索

该文得到了一个反常识的结论&#xff0c;当无关的噪声文档放在正确的位置时&#xff0c;实际上有助于提高RAG的准确性。 摘要 检索增强生成&#xff08;RAG&#xff09;系统代表了传统大语言模型&#xff08;大语言模型&#xff09;的显着进步。 RAG系统通过整合通过信息检索…

Redission--布隆过滤器解决缓存穿透问题

布隆过滤器在缓存穿透问题中的使用 布隆过滤器的核心是一个位数组 布隆过滤器的误判 使用Redission的布隆过滤器步骤 添加 Redission 依赖&#xff1a;首先需要将 Redission 添加到你的 Java 项目中&#xff0c;你可以通过 Maven 来添加 Redission 的依赖。 创建 Redissio…

我的C++奇迹之旅:内联函数和auto关键推导和指针空值

文章目录 &#x1f4dd;内联函数&#x1f320; 查看内联函数inline方式&#x1f309;内联函数特性&#x1f309;面试题 &#x1f320;auto关键字(C11)&#x1f320; auto的使用细则&#x1f309;auto不能推导的场景 &#x1f320;基于范围的for循环(C11)&#x1f320;范围for的…

Spatio-Temporal Pivotal Graph Neural Networks for Traffie Flow Forecasting

摘要:交通流量预测是一个经典的时空数据挖掘问题,具有许多实际应用。,最近,针对该问题提出了各种基于图神经网络(GNN)的方法,并取得了令人印象深刻的预测性能。然而,我们认为大多数现有方法忽视了某些节点(称为关键节点)的重要性,这些节点自然地与多个其他节点表现出…

IPSEC VPN双机热备份的配置讲解一

IPSEC VPN双机热备份的配置讲解一 VPN 是一种专用网络&#xff0c;可使用公共网络连接两个或两个以上的远程站点。VPN 可使用通过公共网络路由&#xff08;以隧道方式发送&#xff09;的虚拟连接&#xff0c;而非网络之间的专用连接。IPsec VPN 是一项协议&#xff0c;由建立 …

使用神经网络-遗传算法优化神经网络-风电预测故障(BP,GABP,matlab)

本项目是故障预测&#xff0c;不是时序预测&#xff0c;本质还是分类问题 1 数据集介绍 特征文件&#xff1a; 标签文件&#xff1a;共计4个标签&#xff0c;其中大多数都是正常的&#xff0c;其他是3个不正常的类别 2 使用BP网络 2.1 读取数据&#xff0c;然后选择几个…

迷茫下是自我提升

长夜漫漫&#xff0c;无心睡眠。心中所想&#xff0c;心中所感&#xff0c;忧愁当前&#xff0c;就执笔而下&#xff0c;写下这篇文章。 回忆过往 回想当初为啥学前端&#xff0c;走前端这条路&#xff0c;学校要求嘛&#xff0c;兴趣爱好嘛&#xff0c;还是为了钱。 时间带着…

【PostgreSQL】技术传承:使用Docker快速部署PostgreSQL数据库

前言 PostgreSQL的重要贡献者Simon Riggs因一起坠机事故不幸离世。Simon Riggs是英国著名的软件与服务领导者&#xff0c;也是PostgreSQL的主要开发者和贡献者。事故发生在英国当地时间3月26日13:41分&#xff0c;当时他驾驶的私人通用航空Cirrus SR22飞机在英国达克斯福德机场…

HTTP详解及代码实现

HTTP详解及代码实现 HTTP超文本传输协议 URL简述状态码常见的状态码 请求方法请求报文响应报文HTTP常见的HeaderHTTP服务器代码 HTTP HTTP的也称为超文本传输协议。解释HTTP我们可以将其分为三个部分来解释&#xff1a;超文本&#xff0c;传输&#xff0c;协议。 超文本 加粗样…

基于Unet的BraTS 3d 脑肿瘤医学图像分割,从nii.gz文件中切分出2D图片数据

1、前言 3D图像分割一直是医疗领域的难题&#xff0c;在这方面nnunet已经成为了标杆&#xff0c;不过nnunet教程较少&#xff0c;本人之前跑了好久&#xff0c;一直目录报错、格式报错&#xff0c;反正哪里都是报错等等。并且&#xff0c;nnunet对于硬件的要求很高&#xff0c…

基于51单片机电子钟闹钟设计

基于51单片机电子钟闹钟设计 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff09; 功能介绍 具体功能&#xff1a; 1.LCD1602实时显示时间和闹钟时间&#xff1b; 2.可整点报时。 3.按键设置时间、闹钟。 4.使用蜂鸣器报时和响闹钟&#xff1b; ​演示视频&…

CCIE-14-MPLS_and_BGP

目录 实验条件网络拓朴 环境配置开始配置配置MPLSR1访问R6检测结果R6访问R1检测结果 实验条件 网络拓朴 环境配置 在我的资源里可以下载&#xff08;就在这篇文章的开头也可以下载&#xff09; 开始配置 R1<->R2&#xff1a;EBGP R2<->R5&#xff1a;IBGP&…

Azkaban集群模式部署详细教程

序言 Azkaban是一个用于工作流程调度和任务调度的开源工具&#xff0c;它可以帮助用户轻松地管理和监控复杂的工作流程。Azkaban的架构设计旨在提供高度可扩展性和可靠性&#xff0c;同时保持易用性和灵活性。 Azkaban的架构可以分为三个主要组件:Executor、Web Server和db数据…

FebHost:什么是土耳其.TR域名?

当前互联网高速发展,一个国家的顶级域名已成为其网络形象的重要标识。近期,土耳其国家顶级域名”.TR”引起了广泛关注,成为业界热议的话题。 作为代表土耳其共和国的国家顶级域名(ccTLD),.TR域名于1991年首次引入,由土耳其科技和信息技术部负责管理。除了常见的”.com.tr”、”…

JavaEE 初阶篇-生产者与消费者模型(线程通信)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 生产者与消费者模型概述 2.0 在生产者与消费者模型中涉及的关键概念 2.1 缓冲区 2.2 生产者 2.3 消费者 2.4 同步机制 2.5 线程间通信 3.0 实现生产者与消费者模…

【大数据存储】spark-编程

实验8-spark编程 实验&#xff1a;编写Spark应用程序&#xff08;掌握Spark应用程序的编写、编译打包和运行方法&#xff09; 1、对于两个输入文件A和B&#xff0c;编写Spark独立应用程序&#xff0c;对两个文件进行合并&#xff0c;并剔除其中重复的内容&#xff0c;得到一个…

IMU参数辨识及标定

IMU参数辨识及标定 一、标定参数分析 标定的本质是参数辨识。首先明确哪些参数可辨识&#xff0c;其次弄清怎样辨识。 参数包括陀螺仪和加速度计各自的零偏、标度因数、安装误差。 IMU需要标定的参数主要是确定性误差和随机误差&#xff0c;确定性误差主要标定bias&#xff0…

多线程学习-线程池

目录 1.线程池的作用 2.线程池的实现 3.自定义创建线程池 1.线程池的作用 当我们使用Thread的实现类来创建线程并调用start运行线程时&#xff0c;这个线程只会使用一次并且执行的任务是固定的&#xff0c;等run方法中的代码执行完之后这个线程就会变成垃圾等待被回收掉。如…

AcWing2069.网格分析

【题目链接】2069. 网络分析 - AcWing题库 输入样例1&#xff1a; 4 8 1 1 2 2 1 10 2 3 5 1 4 1 2 2 2 1 1 2 1 2 4 2 2 1输出样例1&#xff1a; 13 13 5 3 【代码及详细注释】 #include<bits/stdc.h> using namespace std; const int N1e510; int n,m,p[N],d[N]; /…