【STL九】关联容器——map容器、multimap容器

2023-05-16

【STL九】关联容器——map容器、multimap容器

  • 一、map简介
  • 二、头文件
  • 三、模板类
  • 四、map的内部结构
  • 五、成员函数
    • 1、迭代器
    • 2、元素访问
    • 3、容量
    • 4、修改操作
    • ~~5、操作~~
    • 5、查找
    • 6、查看操作
  • 六、demo
    • 1、查找find
    • 2、查找lower_bound、upper_bound
    • 3、insert、emplace() 和 emplace_hint()
  • 七、multimap

一、map简介

在这里插入图片描述

  • map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。
  • key和value都必须是可复制的(copyable),可移动的(movable);
  • 在使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。

默认情况下,map 容器选用std::less排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater)

  • 对于指定的排序准则而言,key必须是可比较的(comparable)。

使用 map 容器存储的各个键值对,键的值既不能重复也不能被修改

二、头文件

#include<map>

三、模板类

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T>>
> class map;

四、map的内部结构

  • map/multimap通常以平衡二叉树完成;(同其他关联容器)
  • map和multimap会根据元素的key自动对元素排序。
    • 这样一来,根据已知的key查找某个元素时就能够有很好的效率,
    • 而根据已知的value查找元素时,效率就很糟糕。
  • 自动排序这一性质使得map和multimap身上有一个很重要的限制:你不可以直接改变元素的key.(因为这会破坏正确次序)

要修改元素的key,必须先移除拥有该key的元素,然后插入拥有新key/value的元素。(如果value非常量,就可以修改)

在这里插入图片描述

五、成员函数

1、迭代器

成员函数功能
begin()同array容器
end()同array容器
rbegin()同array容器
rend()同array容器
cbegin()同array容器
cend()同array容器
crbegin()同array容器
crend()同array容器

2、元素访问

成员函数功能
operator[]同array容器
at(n)同array容器
front()同array容器
back()同array容器
data()同array容器

3、容量

成员函数功能
size()同array容器
max_size()同array容器
empty()同array容器
reserve同vector容器
capacity同vector容器
shrink_to_fit同vector容器

4、修改操作

成员函数功能
clear()同vector容器
insert()同vector容器
insert_or_assign(C++17)插入元素,或若键已存在则赋值给当前元素
emplace()同vector容器
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
try_emplace(C++17)若键不存在则原位插入,若键存在则不做任何事
erase()同vector容器
push_back()同vector容器
emplace_back()同vector容器
pop_back()同vector容器
push_front()同vector容器
emplace_front()同vector容器
pop_front()同vector容器
resize()同vector容器
swap()同vector容器
extract(C++17)从另一容器释出结点
merge(C++17)从另一容器接合结点

5、操作

成员函数功能
merge()list容器
splice()list容器
remove(val)list容器
remove_if()list容器
reverse()list容器
unique()list容器
sort()list容器

5、查找

成员函数功能
count(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。
find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
contains (C++20)检查容器是否含有带特定键的元素
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。
lower_bound(key)返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

6、查看操作

成员函数功能
key_comp返回用于比较键的函数
value_comp返回用于在value_type类型的对象中比较键的函数。

六、demo

1、查找find

  • 返回值
    指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。
#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    cout << "i can find 小c:" << endl;

    auto ite = mymap.find("小c");
    cout << ite->first << "=" << ite->second << endl << endl;

    auto ite2 = mymap.find("c");
    if (ite2 == mymap.end())
    {
        cout << "i can not find c!" << endl;
        // cout << ite->first << "=" << ite->second << endl << endl; //找不到时输出会报错的
    }
    return 0;
}

输出

i can find 小c:
小c=家在濮阳

i can not find c!

2、查找lower_bound、upper_bound

返回值

  • lower_bound:指向首个不小于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器
  • upper_bound:指向首个大于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器

正常场景

#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    //找到第一个键的值不小于 "小c" 的键值对
    auto iter = mymap.lower_bound("小c");
    cout << "lower:" << iter->first << " " << iter->second << endl;

    //找到第一个键的值大于 "小c 的键值对
    iter = mymap.upper_bound("小c");
    cout << "upper:" << iter->first << " " << iter->second << endl;
    
    return 0;
}

输出

lower:小c 家在濮阳
upper:小d 没有家

临界场景

#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    //找到第一个键的值不小于 "小c" 的键值对
    auto iter = mymap.lower_bound("小d");
    cout << "lower:" << iter->first << " " << iter->second << endl;

    //找到第一个键的值大于 "小c 的键值对
    iter = mymap.upper_bound("小d");
    if (iter == mymap.end())
    {
        cout << "i can not find uper load 小d!" << endl;
    }

    return 0;
}

输出

lower:小d 没有家
i can not find uper load 小d!

3、insert、emplace() 和 emplace_hint()

  • insert
    insert() 方法返回的是迭代器,而不再是 pair 对象:
    • 如果插入成功,insert() 方法会返回一个指向 map 容器中已插入键值对的迭代器;
    • 如果插入失败,insert() 方法同样会返回一个迭代器,该迭代器指向 map 容器中和 val 具有相同键的那个键值对。
#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    auto ret = mymap.insert({ "小e","家在台湾"});
    cout << "insert:" << ret.first->first << " " << ret.first->second << "=" << ret.second << endl;

    ret = mymap.insert({ "小e","家在台湾" });
    cout << "insert:" << ret.first->first << " " << ret.first->second << "=" << ret.second << endl;

    return 0;
}

输出

insert:小e 家在台湾=1
insert:小e 家在台湾=0

  • emplace
    emplace() 和 emplace_hint() 是 C++ 11 标准加入到 set 类模板中的,相比具有同样功能的 insert() 方法,完成同样的任务,emplace() 和 emplace_hint() 的效率会更高。
#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    auto ret = mymap.emplace( "小e","家在台湾");
    cout << "emplace:" << ret.first->first << " " << ret.first->second << "=" << ret.second << endl;

    ret = mymap.emplace( "小e","家在台湾" );
    cout << "emplace:" << ret.first->first << " " << ret.first->second << "=" << ret.second << endl;

    return 0;
}

输出

emplace:小e 家在台湾=1
emplace:小e 家在台湾=0

  • emplace_hint
#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    map <string, string> mymap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
    };
    
    auto iter = mymap.emplace_hint(mymap.begin(), "小e","家在台湾");
    cout << "emplace_hint:" << iter->first << " " << iter->second << endl;

    iter = mymap.emplace_hint(mymap.begin(), "小e", "家在台湾");
    cout << "emplace_hint:" << iter->first << " " << iter->second << endl;

    return 0;
}

输出

emplace_hint:小e 家在台湾
emplace_hint:小e 家在台湾

虽然 emplace_hint() 方法指定了插入键值对的位置,但 map 容器为了保持存储键值对的有序状态,可能会移动其位置。(如下图)
在这里插入图片描述

七、multimap

map 容器的区别在于,multimap 容器中可以同时存储多(≥2)个键相同的键值对。

由于 multimap 容器可存储多个具有相同键的键值对,因此表 1 中的 lower_bound()、upper_bound()、equal_range() 以及 count() 成员方法会经常用到。

  • 模板类
multimap 容器类模板的定义如下:
template < class Key,                                   // 指定键(key)的类型
           class T,                                     // 指定值(value)的类型
           class Compare = less<Key>,                   // 指定排序规则
           class Alloc = allocator<pair<const Key,T> >  // 指定分配器对象的类型
           > class multimap;
  • demo
template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class multimap;
  • demo
#include <iostream>
#include <string>       // string
#include<map>
using namespace std;
int main() {
    // 调用构造函数 1,也就是默认构造函数
    multimap <string, string> mymultimap{
        {"小b","家在西安"},
        {"小c","家在濮阳"},
        {"小a","家在北京"},
        {"小d","没有家"},
        {"小d","也没有家"},
    };

    //输出 mymultimap 容器中存储键为 'b' 的键值对的数量
    cout << mymultimap.count("小d") << endl;
    
    for (auto iter = mymultimap.begin(); iter != mymultimap.end(); ++iter) {
        cout << iter->first << " " << iter->second << endl;
    }

    return 0;
}

2
小a 家在北京
小b 家在西安
小c 家在濮阳
小d 没有家
小d 也没有家

参考:
1、C++ STL 容器库 中文文档
2、STL教程:C++ STL快速入门
3、https://www.apiref.com/cpp-zh/cpp/header.html
4、https://en.cppreference.com/w/cpp/container

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STL九】关联容器——map容器、multimap容器 的相关文章

  • 日本原装COM 3600F专业型空气负离子检测仪 --CR1000采集

    Public PTemp Batt volt Public instring string As String 36 Public Num spilt 3 As String 3 Alias Num spilt 1 61 ION FM Pu
  • java FlowLayout示例

    java FlowLayout示例 xff1a import java awt FlowLayout import javax swing JLabel import javax swing WindowConstants import j
  • Get 一个显示界面,与数采串口通信

    程序第一步 xff1a 显示 数据来源 xff0c CR1000数据采集器 xff0c 5秒采集并存储上传 第二步 xff1a 存储 TXT文档存储 xff0c 逗号分隔 xff0c 每月创建一个新的文件 xff0c 可以另存为excel文
  • UART通信协议

    UART通信协议 一 UART是什么 xff1f 1 同步串口通信 vs 异步串口通信2 串行通信 二 通信协议三 工作原理四 特点 一 UART是什么 xff1f 通用异步收发传输器 xff08 Universal Asynchronou
  • win10右下角的通知区域

    属性 gt 通知和操作 gt 选择在任务栏上显示哪些图标 gt
  • UART一对多通信的方法

    通常 xff0c uart为单对单通信 xff0c 当用到一对多时可以用RS485 然而有时候我们MCU的uart口只剩一个 xff0c 又要接多个uart的外围芯片 xff0c 这时如果转成RS485需要加多个485收发器 xff0c 成
  • 全网最全的 postman 工具使用教程

    正文如下 xff0c 如果觉得有用欢迎点赞 关注 postman是一款支持http协议的接口调试与测试工具 xff0c 其主要特点就是功能强大 xff0c 使用简单且易用性好 无论是开发人员进行接口调试 xff0c 还是测试人员做接口测试
  • 星际争霸1终于可以在win10上运行了

    win7的时候 xff0c 星际争霸1就不能运行 xff0c 只好装了个虚拟机 xff0c 在虚拟机里玩 刚刚更新到了win10 xff0c 总觉得在虚拟机里玩不是个事 xff0c 就去网上搜索 xff0c 终于发现了办法 在 StarCr
  • windows下编译opencv 3.4.0

    为了方便后期的调试 xff0c 自己动手编译opencv3 4 0 xff0c 这样有需要的时候还可以自己修改修改源代码 通常来说 xff0c 编译32位比较简单 xff0c 直接用cmake生成编译的工程就行了 xff0c 但64位就比较
  • opencv添加的新接口clearVec()的实现

    自己编译的opencv xff0c 之前文章有说添加了这个接口 xff0c 也有上传3 3 0版本添加这个接口之后编译好的库 xff0c 但是没有把实现过程展现出来 xff0c 导致有些朋友问我如何实现的 xff0c 今天把这个实现放出来
  • 苏泊尔电饭煲不工作的维修

    本篇文章与其说是维修 xff0c 倒不如说成是 拆 xff0c 因为维修相对容易 xff0c 但想拆开却很艰难 xff0c 大部分的时间都花在了拆的工作上面 老家伙的样子如下 型号为 xff1a CYSB50FC99 100 xff0c 铭
  • 萨克斯吹不响的解决办法

    刚开始吹萨克斯 xff0c 发现总是吹不响 看各种入门的文章 xff0c 很多都强调口型的重要性 xff0c 各文章说得也都差不多 xff0c 我仔细捉摸 xff0c 不断尝试 xff0c 似乎还是不得要领 特别是安装好之后 xff0c 很
  • vs2010制作安装工程

    这里的安装工程 xff0c 是指制作安装包 xff0c 而不是vs2010的安装包 用向导生成一个安装工程 xff0c 通常会直接打开一个文件编辑窗口 xff1a 这个窗口很容易编辑 xff0c 把所有要安装的文件拖到 应用程序文件夹 上
  • windows下编译ffmpeg源代码

    由于工作原因 xff0c 需要使用ffmpeg在windows下进行代码跟踪 于是 xff0c 上网找相关文章 xff0c 搜索出来有很多 xff0c 经过查看 xff0c 其中的一个英文网站是最好的 xff0c 网址 xff1a http
  • 注册控件失败之一:提示0x80040200错误的处理办法

    今天有客户反馈说控件无法注册 xff0c 晕 xff0c 这问题好容易困扰开发者以及客服人员 xff0c 但是环境千差万别 xff0c 很难做到完全自动化 出现的错误号码有很多 xff0c 但相对的0x80040200这个号码出现的概率较其
  • win10+ubuntu23.04双系统安装

    win10 win10先安装好 xff08 确保主板上各个螺丝稳定 xff0c 至少4对螺丝 43 铜柱 xff0c 否则会各种蓝屏 xff09 如果双系统安装失败了 xff0c 连win10都进不去了 xff0c 用原版ISO刻录的U盘或
  • 冷门指标移中平均线和多空指数的完美结合(一定要看)

    注 xff0c 原贴地址 xff1a http blog sina com cn s blog 7f0a6fa50101hyls html 在此谨以记录防止原帖无法打开为忧 冷门指标移中平均线和多空指数的完美结合 一定要看 xff09 20
  • LINUX下安装QT的惨痛经历

    安装QT的惨痛经历 目标 xff1a 2012 4月下旬 xff0c 计划开始在linux上安装QT和ffmpeg xff0c 准备摸索一下视频客户端的开发 以下是安装过程 由于没有额外的电脑 xff0c 所以使用了虚拟机安装 电脑上刚好有
  • Linux下CAN总线速率设置,socketCAN。

    背景 xff1a 飞思卡尔Freescale的ARM9处理器i MX25系列 socketCAN对于在Linux下操作CAN总线非常的快捷方便 xff0c 其配置方法和在Linux下对网卡的配置相似 xff0c 方法如下 xff1a 1 i
  • c++在Linux环境下的套接字Tcp通信例子(demo)

    demo包括服务端和客户端的通信 xff0c 发送端发送格式为先发送长度为5的字符串数据 xff0c 告知对方接下来的数据长度 xff0c 接收端首先接收到消息长度 xff0c 再根据消息长度接受接下来的消息 服务端 xff1a inclu

随机推荐

  • yolo_mark工具的使用

    之前自己编译了一下yolo mark用来标注样本 我编译时yolo mark依赖了opencv3 2 0 当时为了方便直接把yolo mark exe放到编译yolo的文件夹 现在要在其他地方使用 xff0c 就把所有文件整理出来 其中op
  • GStreamer与opencv实现rtsp推流

    文章目录 前言安装库代码总结 前言 最近工作遇到瓶颈了呀 xff01 xff01 xff01 公司分配给我的任务是deepstream部署 xff0c 太难了 xff0c gstreamer语言学的我头皮发麻 xff01 xff01 xff
  • 【STM32学习5】STM32使用printf函数 打印到电脑串口助手

    本文所使用的方法与代码参考自正点原子 xff0c 如果想要详细了解这方面的知识 xff0c 请阅读正点原子官方提供的文档 一 背景 在开发STM32应用时 xff0c 将一些信息通过串口打印到电脑上是常用的调试手段 C语言标准库中的prin
  • linux下socketCAN实现反转过滤——CAN_INV_FILTER的使用

    关于Linux中socket can怎么使用 xff0c CSDN上已经有很多文章介绍 本文重点记录can filter中的 CAN INV FILTER的使用 xff0c 很多文章对此一笔带过 xff0c 且很多文章翻译不全 xff0c
  • [摘抄-Socket-学习中]UDP通信基础代码-server端

    include lt stdio h gt include lt stdlib h gt include lt string h gt include lt sys socket h gt include lt netinet in h g
  • 四轴飞行器初步——器件选择

    电机 图1 图2 四轴飞行器可以采用无刷电机 xff08 图1 xff09 xff0c 也可以采用有刷电机 xff08 图2 xff09 前者载重能力强 xff0c 一般用于稍大型的多轴飞行器 后者一般用 于小型四轴飞行器 xff0c 如c
  • 如何提取小程序中的文字

    打开微信pc端 xff0c 点击小程序图片 打开qq使用长截图功能 打开adobe acrobat破解版 xff0c 进行文字识别 xff0c 即可得到所有内容
  • 导致数据库中数据不一致的根本原因

    数据库中很有可能存在不一致的数据 一般导致数据库中数据不一致的根本原因有三种情况 第一种是数据冗余造成的 xff0c 第二种是并发控制不当造成的 xff0c 第三种是由于某种原因 xff08 比如软硬件故障或者操作错误 xff09 导致数据
  • visual studio的team使用问题小结

    visual studio的team使用问题小结 一 visual studio xff08 2017 xff09 默认浏览器打开team任务和bug二 visual studio xff08 2017 xff09 上传team时 xff0
  • 【STL一】STL组件(容器、迭代器、算法、适配器、函数对象、内存分配器)

    STL一 STL组件 xff08 容器 迭代器 算法 适配器 函数对象 内存分配器 xff09 一 STL二 STL组件 xff08 component xff09 1 stl六大组件2 C 43 43 STL的13个头文件3 stl所有头
  • 【STL二】STL序列式容器(array、vector、deque、list、forward_list)

    STL二 STL序列式容器 xff08 array vector deque list forward list xff09 1 array lt T N gt xff08 数组容器 xff09 2 vector lt T gt xff08
  • 【STL三】序列容器——array容器

    STL三 序列容器 array 一 array简介二 头文件三 模板类四 成员函数1 迭代器2 元素访问3 容量4 操作 五 demo1 容量 xff08 不使用迭代器 xff09 2 使用迭代器3 元素访问 at front back d
  • 【STL四】序列容器——vector容器

    STL容器 序列容器 vector容器 一 简介二 头文件三 模板类四 成员函数1 迭代器2 元素访问3 容量4 修改操作 五 demo1 容量reserve capacity shrink to fit2 修改操作pop back pus
  • 【STL五】序列容器——deque容器

    STL五 序列容器 deque容器 一 简介二 头文件三 模板类四 成员函数1 迭代器2 元素访问3 容量4 修改操作 五 demo1 修改操作insert2 修改操作emplace front3 size 使用注意事项3 1 size 1
  • 【STL六】序列容器——list容器、forward_list容器

    STL六 序列容器 list容器 一 简介二 头文件三 模板类四 成员函数1 迭代器2 元素访问3 容量4 修改操作5 操作 五 demo1 迭代器2 修改操作insert3 操作unique4 操作merge sort5 remove i
  • 【STL七】序列容器——effective STL

    STL七 序列容器 effective STL 一 优先采用emplace系列函数二 调用empty而不是检查size 是否为0 xff1f 1 网上的说法2 验证 xff08 以vector为例 xff0c 其实list也一样 xff09
  • 【并发编程二十一:终章】c++20协程( co_yield、co_return、co_await )

    并发编程二十一 c 43 43 20协程 co yield co return co await xff09 一 协程分类1 控制机制划分2 有栈 xff08 stackfull 无栈 xff08 stackless 划分 二 c 43 4
  • 【STL八】关联容器

    STL八 关联容器 一 简介二 分类三 生成键值对方法一 xff1a map key 61 value四 生成键值对方法二 xff1a pair make pair1 pair2 make pair3 pair make pair 头文件4
  • wps目录设置

    选择导航窗格中的 靠左 选中文档中标题 xff0c 右键选择 2级目录 效果如下 xff1a Reference xff1a 1 wps目录快捷键 wps自动识别目录快捷键 65路由网
  • 【STL九】关联容器——map容器、multimap容器

    STL九 关联容器 map容器 multimap容器 一 map简介二 头文件三 模板类四 map的内部结构五 成员函数1 迭代器2 元素访问3 容量4 修改操作 5 操作 5 查找6 查看操作 六 demo1 查找find2 查找lowe