Day 28 C++ (映射)map 容器 / multimap 容器 (多重映射)

news2025/1/14 17:57:11

文章目录

  • map (映射)
      • 定义
          • 注意
          • 优点
      • map构造和赋值
          • 构造
          • 赋值
          • 示例
      • map大小和交换
          • 函数原型
          • 示例
      • map插入和删除
          • 函数原型
          • 四种插入方式
          • 示例
      • map查找和统计
          • 函数原型
          • 示例
      • map容器排序
  • multimap 容器 (多重映射)
      • 定义
      • 特点
      • 和map的区别
      • 示例

map (映射)

定义

C++中的map是一种关联容器,它提供了一种键-值(key-value)对的存储方式。map容器中的元素是按照键的顺序进行排序的,并且每个键都唯一。通过使用键来访问其相应的值,我们可以在O(log n)的时间复杂度内进行快速的查找、插入和删除操作。

map与set类似,但不同之处在于map存储的是键值对(key-value pair),而set只存储单个元素。每个键值对在map中被视为一个元素,由键(key)和值(value)组成。键用于唯一标识元素,值则是与键相关联的数据。

注意
  • map中所有元素都是pair
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • map 是一个有序容器,所有元素都会根据元素的键值自动排序
  • 每个键只能在 map 中唯一出现。如果插入一个已存在的键,那么新的值会取代旧的值。
优点
  • 快速查找
    map基于红黑树实现,这使得在大量数据情况下,查找操作具有较好的时间复杂度(平均为O(log n))。因此,可以根据key值快速找到value值
  • 有序性
    map以键的顺序进行排序,这意味着通过map迭代器遍历时可以按照键的有序性进行操作。这对于需要按照键的顺序访问数据的场景非常方便。
  • 唯一键
    map中每个键都是唯一的,这意味着相同的键只会出现一次。当需要确保数据中的键是唯一的时,map提供了一种有效的数据结构来实现这一点。
  • 稳定性
    由于map基于红黑树实现,它对插入和删除操作的平均时间复杂度为O(log n),这使得在频繁更新数据的场景中也能保持较好的性能稳定性。

map构造和赋值

构造
  • map<T1, T2> mp; //map默认构造函数:
  • map(const map &mp); //拷贝构造函数
赋值
  • map& operator=(const map &mp); //重载等号操作符
示例

注意:map中所有元素都是成对出现,插入数据时候要使用对组

#include <iostream>
#include <map>

int main() {
    // 创建一个空的map
    std::map<int, std::string> mp;

    // 使用insert插入元素
    mp.insert(std::make_pair(1, "apple"));
    mp.insert(std::make_pair(2, "banana"));
    mp.insert(std::make_pair(3, "orange"));

    // 输出map的元素
    for (const auto& pair : mp) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 使用拷贝构造函数创建一个新的map
    std::map<int, std::string> copyMap(mp);

    // 使用等号操作符进行赋值
    std::map<int, std::string> assignedMap;
    assignedMap = mp;

    return 0;
}

输出
1: apple
2: banana
3: orange


map大小和交换

函数原型
  • size(); //返回容器中元素的数目
  • empty(); //判断容器是否为空
  • swap(st); //交换两个集合容器
示例
#include <iostream>
#include <map>

int main() {
    // 创建一个map
    std::map<int, std::string> mp;

    // 插入一些元素
    mp.insert(std::make_pair(1, "apple"));
    mp.insert(std::make_pair(2, "banana"));
    mp.insert(std::make_pair(3, "orange"));

    // 获取容器中元素的数目
    std::cout << "Size: " << mp.size() << std::endl;

    // 判断容器是否为空
    if (mp.empty()) {
        std::cout << "Map is empty" << std::endl;
    } else {
        std::cout << "Map is not empty" << std::endl;
    }

    // 创建另一个map
    std::map<int, std::string> anotherMap;
    anotherMap.insert(std::make_pair(4, "grape"));
    anotherMap.insert(std::make_pair(5, "kiwi"));

    // 交换两个map
    mp.swap(anotherMap);

    // 输出交换后的结果
    std::cout << "Map after swap:" << std::endl;
    for (const auto& pair : mp) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

输出结果
Size: 3
Map is not empty
Map after swap:
4: grape
5: kiwi

分析
在上述示例中,我们首先创建了一个map<int, string>,并插入了几个键值对。然后我们使用size()函数获取容器中元素的数目,并使用empty()函数判断容器是否为空。

接下来,我们创建了另一个map anotherMap,并插入了一些元素。然后使用swap()函数交换了两个map的内容,将原来的mp与anotherMap进行了交换。最后,我们遍历并输出了交换后的map的元素。

需要注意的是,swap()函数会直接交换两个map的内容,而不是创建副本或者复制元素。


map插入和删除

函数原型
  • insert(elem); //在容器中插入元素。
  • clear(); //清除所有元素
  • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
  • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
  • erase(key); //删除容器中值为key的元素。
四种插入方式
  • m.insert(pair<int, int>(1, 10));

  • m.insert(make_pair(2, 20));

  • m.insert(map<int, int>::value_type(3, 30));

  • m[4] = 40;

注意

map<int, int>::value_type(3, 30) 是一个创建 map 中键值对的方法。它使用了 map 的嵌套类型 value_type,表示键值对的类型。注意,map<int, int>::value_typepair<const Key, T> 的别名,其中 Key 是键的类型,T 是值的类型。

value_type 是 map 类的内部类型,表示键值对的类型。在这里,map<int, int>::value_type 表示 pair<const int, int>,即键为 const int 类型,值为 int 类型的键值对。

这种方式仅适用于 C++03 标准及之前的版本。从 C++11 标准开始,我们可以直接使用简化的插入语法,如 m.insert({3, 30})

示例
#include <iostream>
#include <map>
void printMap(map<int,int>&m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << it->first << " value = " << it->second << endl;
	}
	cout << endl;
}

int main() {
	//插入
	map<int, int> m;
	//第一种插入方式
	m.insert(pair<int, int>(1, 10));
	//第二种插入方式
	m.insert(make_pair(2, 20));
	//第三种插入方式
	m.insert(map<int, int>::value_type(3, 30));
	//第四种插入方式
	m[4] = 40; 
	printMap(m);

	//删除
	m.erase(m.begin());
	printMap(m);
	m.erase(3);
	printMap(m);

	//清空
	m.erase(m.begin(),m.end());
	m.clear();
	printMap(m);
	return 0;
}

在上述示例中,我们首先创建了一个map<int, int>,然后使用四种不同的插入方式向map中插入了一些元素,并使用printMap函数输出map的内容。

接下来,我们使用erase函数删除了第一个元素和键为3的元素,并再次使用printMap函数输出了更新后的map。

最后,我们使用clear函数清空了整个map,并再次使用printMap函数输出了清空后的map。

需要注意的是,map中的元素是按照键的顺序进行排序的,而且键必须是唯一的。同时,使用erase函数删除元素时可以指定要删除的元素的位置或者键值。


map查找和统计

函数原型
  • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;否则返回set.end();
  • count(key); //统计key的元素个数 (对于map,结果为0或者1, 最多一个不重复)
示例
#include <iostream>
#include <map>

int main() {
    std::map<int, int> m;
    
    // 插入元素
    m.insert(std::pair<int, int>(1, 10));
    m.insert(std::pair<int, int>(2, 20));
    m.insert(std::pair<int, int>(3, 30));
    m.insert(std::pair<int, int>(4, 40));

    // 使用 find 函数查找键为 3 的元素
    std::map<int, int>::iterator it = m.find(3);
    if (it != m.end()) {
        std::cout << "键为 3 的元素存在,值为 " << it->second << std::endl;
    } else {
        std::cout << "键为 3 的元素不存在" << std::endl;
    }

    // 使用 count 函数统计键为 4 的元素个数
    int count = m.count(4);
    std::cout << "键为 4 的元素个数为 " << count << std::endl;

    // 查找一个不存在的键
    it = m.find(5);
    if (it != m.end()) {
        std::cout << "键为 5 的元素存在,值为 " << it->second << std::endl;
    } else {
        std::cout << "键为 5 的元素不存在" << std::endl;
    }

    return 0;
}

输出
键为 3 的元素存在,值为 30
键为 4 的元素个数为 1
键为 5 的元素不存在

在上述示例中,我们首先创建了一个map<int, int>并向其中插入了几个元素。然后,我们使用find(key)函数来查找键为 3 的元素,并根据返回的迭代器判断该元素是否存在。

接下来,我们使用count(key)函数统计键为 4 的元素的个数。

最后,我们使用find(key)函数查找一个不存在的键 5,并根据返回的迭代器判断该元素是否存在。

需要注意的是,对于count(key)函数来说,由于map容器的特性,它的返回值要么是 0(表示键不存在),要么是 1(表示键存在)。因为map 中每个键都是唯一的。


map容器排序

  • map容器默认排序规则为 按照key值进行 从小到大排序
  • 利用仿函数可以指定map容器的排序规则
  • 对于自定义数据类型,map必须要指定排序规则,同set容器

重载 operator() 运算符是定义一个仿函数的必要条件。实际上,仿函数就是一个对象,在使用仿函数时,我们可以像调用函数一样使用它进行计算。在 C++ 中,仿函数可以重载多个运算符,但重载 operator() 运算符是最常见的情况,因为它使得对象可以被像函数一样调用,并且提供了比较接近函数调用的语法。除了重载 operator() 运算符外,仿函数还可以根据需要重载其他运算符,例如 operator+operator- 等运算符,以实现特定的功能。

示例:

#include <iostream>
#include <map>

// 自定义仿函数类来指定排序规则
struct MyComparator {
    bool operator()(int a, int b) const {
        return a > b; // 从大到小排序
    }
};

int main() {
    std::map<int, std::string, MyComparator> m; // 使用自定义排序规则的 map

    // 向 map 中插入元素
    m.insert(std::pair<int, std::string>(3, "Alice"));
    m.insert(std::pair<int, std::string>(1, "Bob"));
    m.insert(std::pair<int, std::string>(4, "Charlie"));
    m.insert(std::pair<int, std::string>(2, "David"));

    // 打印按照自定义排序规则排序后的结果
    for (const auto& pair : m) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    return 0;
}

输出
4: Charlie
3: Alice
2: David
1: Bob

在上述示例中,我们定义了一个名为 MyComparator 的仿函数类,用于指定排序规则。该仿函数类重载了 operator() 运算符,其中通过返回 a > b 来实现从大到小排序。

然后,我们创建了一个类型为 map<int, string> 的 map 容器,并将自定义的 MyComparator 类作为第三个模板参数传递给 map,以指定排序规则为从大到小。

接下来,我们向 map 中插入了几个元素,并通过遍历 map 打印出按照自定义排序规则排序后的结果。

需要注意的是,在使用自定义排序规则时,关键是要将该规则作为 map 的第三个模板参数进行指定,以告诉 map 使用自定义排序规则。

multimap 容器 (多重映射)

定义

multimap 是 C++ STL 中的一个关联容器,它提供了一种键值对的存储方式,允许一个键对应多个值。multimap 容器中的元素按照键的自然顺序进行排序,并且可以有重复的键。

特点

可以有重复的键。
键和值可以是任意数据类型。
键值对是按照键的自然顺序进行排序的。
提供了高效的插入、查找和删除操作

和map的区别

multimap 可以有多个相同的键,map不行,其他二者几乎一致

示例

#include <iostream>
#include <map>

int main() {
    std::multimap<int, std::string> mm;

    // 插入键值对
    mm.insert(std::pair<int, std::string>(3, "Alice"));
    mm.insert(std::pair<int, std::string>(1, "Bob"));
    mm.insert(std::pair<int, std::string>(2, "Charlie"));
    mm.insert(std::pair<int, std::string>(3, "David"));

    // 遍历 multimap
    for (const auto& pair : mm) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

输出
1: Bob
2: Charlie
3: Alice
3: David

在上述示例中,我们创建了一个 multimap<int, string> 类型的 multimap 容器,并向其中插入了几个键值对。其中,键是 int 类型,值是 string 类型。

然后,我们通过遍历 multimap 容器,打印出所有的键值对。

需要注意的是,由于 multimap 容器允许有重复的键,因此在遍历时,可能会输出相同键的多个值。

在这里插入图片描述

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

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

相关文章

Windows - UWP - 为UWP应用创建桌面快捷方式

Windows - UWP - 为UWP应用创建桌面快捷方式 前言 这是一个较为简单的方式&#xff0c;不需要过多的命令行。 How 首先Win R -> shell:AppsFolder -> 回车&#xff0c; 这将显示电脑上的已安装应用&#xff08;Win32 & UWP&#xff09;&#xff1a; 找到想要创建…

uniapp使用阿里矢量库

然后解压复制全部到你的项目文件 最后只要这几个 然后引入 最后在你需要的页面使用

多线程的同步与互斥

文章目录 线程安全问题多线程互斥互斥量mutex互斥锁的使用理解锁加锁如何做到原子性对mutex做封装 可重入与线程安全死锁 线程同步条件变量条件变量函数接口理解条件变量条件变量的使用 线程安全问题 首先来看一段代码&#xff0c;该代码是一个多线程抢票的逻辑 #include<…

go的gin和gorm框架实现切换身份的接口

使用go的gin和gorm框架实现切换身份的接口&#xff0c;接收前端发送的JSON对象&#xff0c;查询数据库并更新&#xff0c;返回前端信息 接收前端发来的JSON对象&#xff0c;包含由openid和登陆状态组成的一个string和要切换的身份码int型 后端接收后判断要切换的身份是否低于该…

排列数字 (dfs)

希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注~ 不清楚蓝桥杯考什么的点点下方&#x1f447; 考点秘籍 想背纯享模版的伙伴们点点下方&#x1f447; 蓝桥杯省一你一定不能错过的模板大全(第一期) 蓝桥杯省一你一定不能错过的模板大全…

Dubbo2-概述

Dubbo 阿里公司开源的一个高性能&#xff0c;轻量级的javaRPC&#xff08;远程服务调用方案&#xff09;框架&#xff0c;提供高性能远程调用方案以及SOA服务治理方案 Dubbo架构 节点角色说明&#xff1a; Provider:服务提供方 Container:服务运行容器 Consumer:调用远程服务…

中科亿海微RAM使用

引言 FPGA&#xff08;Field Programmable Gate Array&#xff0c;现场可编程门阵列&#xff09;是一种可编程逻辑设备&#xff0c;能够根据特定应用的需求进行配置和重新编程。在FPGA中&#xff0c;RAM&#xff08;Random Access Memory&#xff0c;随机存取存储器&#xff09…

HTML详解连载(3)

HTML详解连载&#xff08;3&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽表单作用使用场景 input标签基本使用示例type属性值以及说明 input标签占位文本示例注意 单选框 radio代码示例 多选框-checkbox注意代码示例 文本域作用标签&#xff1…

《3D 数学基础》12 几何图元

目录 1 表达图元的方法 1.1 隐式表示法 1.2 参数表示 1.3 直接表示 2. 直线和射线 2.1 射线的不同表示法 2.1.1 两点表示 2.1.2 参数表示 2.1.3 相互转换 2.2 直线的不同表示法 2.2.1 隐式表示法 2.2.2 斜截式 2.2.3 相互转换 3. 球 3.1 隐式表示 1 表达图元的方…

运维监控学习笔记4

系统监控&#xff1a; CPU&#xff1a; 内存&#xff1a; IO INPUT/OUTPUT&#xff08;网络、磁盘&#xff09; CPU三个重要概念&#xff1a; 上下文切换&#xff1a;CPU调度器实施的进程的切换过程&#xff0c;称为上下文切换。CPU寄存器的作用。 上下文切换越频繁&#…

keil下载程序具体过程4:flash下载算法

引言 本篇文章将介绍flash算法文件&#xff0c;阐述从jlink如何下载镜像文件写入到内部的falsh。 一、XIP 在谈flash下载算法文件时&#xff0c;先说明XIP是什么。 芯片的启动方式有很多种&#xff1a;可以从RAM中启动、内部的flash、外部的flash等等&#xff08;还有从sd卡、…

CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

文章目录 查询链接问题请求超时原因解决谷歌浏览器超时问题办法&#xff08;失败了&#xff09;谷歌浏览器不支持设置请求超时时间&#xff08;谷歌浏览器到底有没限制请求超时&#xff1f;貌似没有限制&#xff1f;&#xff09;看能否脱离浏览器请求&#xff0c;我们查看关键代…

基于C++实现了最小反馈弧集问题的三种近似算法(GreedyFAS、SortFAS、PageRankFAS)

该项目是一个基于链式前向星存图、boost&#xff08;boost::hash、asio线程池&#xff09;以及emhash7/8的非官方实现&#xff0c;实现了最小反馈弧集问题的三种近似算法。该问题是在有向图中找到最小的反馈弧集&#xff0c;其中反馈弧集是指一组弧&#xff0c;使得从这些反馈弧…

环境与分支的详细介绍及其关联(开发、测试、预发布、生产)

文章目录 前言一、开发环境&#xff08;dev&#xff09;二、测试环境&#xff08;test&#xff09;三、预发布环境&#xff08;pre&#xff09;四、生产环境&#xff08;pro&#xff09;五、环境与分支的关系总结 前言 在现代软件开发中&#xff0c;前端项目的开发和部署往往需…

【wiki】电竞助手掉落提醒 EsportsHelper「Webhook」「钉钉」「饭碗警告」「企业微信」「Discord」

介绍 本项目链接 Github电竞助手链接 github上项目电竞助手(EsportsHelper)的掉落提醒配置教程,当有掉宝的时候会发送你信息提示. 至于这个脚本是怎么使用的简单说一下,就是通过自动观看英雄联盟直播 从而获取奖励(仅限直营服),有兴趣的可以去github上看readme,非常详细,支持…

广联达 Linkworks办公OA SQL注入+后台文件上传漏洞复现(HW0day)

0x01 产品简介 广联达Linkworks办公OA&#xff08;Office Automation&#xff09;是一款综合办公自动化解决方案&#xff0c;旨在提高组织内部的工作效率和协作能力。它提供了一系列功能和工具&#xff0c;帮助企业管理和处理日常办公任务、流程和文档。 0x02 漏洞概述 由于 广…

hackNos靶机

靶机训练1 - hackNos: Os-hackNos 靶机平台 Vulnhub 是一个提供各种漏洞环境的靶场平台&#xff0c;供安全爱好者学习使用&#xff0c;大部分环境是做好的虚拟机镜像文件&#xff0c;镜像预先设计了多种漏洞&#xff0c;需要使用VMware或者VirtualBox运行。每个镜像会有破解的目…

【CSS学习笔记】

学习内容 1.css是什么 2.CSS怎么用&#xff08;快速入门&#xff09; 3.CSS选择器&#xff08;重点 难点&#xff09; 4.美化页面&#xff08;文字、阴影、超链接、列表、渐变…&#xff09; 5.盒子模型 6.浮动 7.定位 8.网页动画&#xff08;特效&#xff09; 1.什么是CSS C…

Reinforcement Learning with Code 【Chapter 10. Actor Critic】

Reinforcement Learning with Code 【Chapter 10. Actor Critic】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of …

Blazor简单教程(2):布局

文章目录 前言布局自定义布局默认布局 前言 我们现在主流的页面都是单页面Layout布局&#xff0c;即一个页面有侧边栏&#xff0c;抬头&#xff0c;下边栏&#xff0c;中间主题。 BootstrapBlazor UI&#xff0c; Blazor Server 模式配置 布局 自定义布局 注入LayoutCompon…