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

文章目录

  • 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() {// 创建一个空的mapstd::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;}// 使用拷贝构造函数创建一个新的mapstd::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() {// 创建一个mapstd::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;}// 创建另一个mapstd::map<int, std::string> anotherMap;anotherMap.insert(std::make_pair(4, "grape"));anotherMap.insert(std::make_pair(5, "kiwi"));// 交换两个mapmp.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"));// 遍历 multimapfor (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.hqwc.cn/news/71122.html

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

相关文章

Python系统学习1-9-类一之类语法

一、类之初印象 1、类就是空表格&#xff0c;将变量&#xff08;列名&#xff09;和函数&#xff08;行为&#xff09;结合起来 2、创建对象&#xff0c;表达具体行 3、创建类就是创建数据的模板 --操作数据时有提示 --还能再组合数据的行为 --结构更加清晰 4、类的内存分配…

【深度学习 | 感知器 MLP(BP神经网络)】掌握感知的艺术: 感知器和MLP-BP如何革新神经网络

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

iPhone(iPad)安装deb文件

最简单的方法就是把deb相关的文件拖入手机对应的目录&#xff0c;一般是DynamicLibraries文件夹 参考&#xff1a;探讨手机越狱和安装deb文件的几种方式研究 1、在 Mac 上安装 dpkg 命令 打包 deb 教程之在 Mac 上安装 dpkg 命令_xcode打包root权限deb_qq_34810996的博客-CS…

Android上架商城 隐私政策需要网页 没有怎么办

Android开发的项目上架商城的时候会需要你填写url&#xff0c;但其实并不需要真的去发布一个网站 使用腾讯文档新建文档 填写隐私政策 点击生成网页 再将网址填写即可 下面我找到的一个隐私政策文档供大家参考 将XXXX应用一键替换为自己的应用 将XXXXXX公司一键替换为公司 …

.Net Core 动态加载和卸载程序集

从 .Net Core 3.0开始支持程序集的加载和卸载&#xff0c;在 .Net FrameWork中使用独立的应用程序域来实现同样的功能&#xff0c;.Net Core 不支持创建多个应用程序域&#xff0c;所以无法使用多个应用程序域来实现程序集动态加载和卸载。 AssemblyLoadContext 程序集加载上下…

07- RTC实时时钟

RTC实时时钟 RTC实时时钟RTC时钟来源&#xff1a;RTC的特征&#xff1a;简化的RTC框图及原理简介&#xff1a;RTC由两部分组成&#xff1a;RTC相关库函数&#xff1a;库函数的讲解和使用&#xff1a;RTC配置步骤&#xff1a; 示例 RTC实时时钟 RTC时钟来源&#xff1a; RTC的特…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

WX1860- ngbe-1.2.5 xdp程序在路由模式下,使用iperf工具测试数据包不转发,用jmeter可以

本地验证时重定向iperf包有出现calltrace错误&#xff0c;经推断&#xff0c;系统PAGE_SIZE<8k时可能出现&#xff08;getconf PAGE_SIZE指令可查看&#xff09;&#xff0c;按下图将ngbe_main.c的2350行ngbe_rx_bufsz改为ngbe_rx_pg_size可修复。其次&#xff0c;需要将加载…

RabbitMQ启动服务报错1067解决方案

首先&#xff1a; 你的 Erlang正确下载安装&#xff0c;且配置完成环境变量&#xff0c;可在命令行键入erl&#xff0c;若显示erlang版本则说明环境变量配置成功。如下&#xff1a; 原因分析&#xff1a; 1. 电脑名称为中文 2. erlang和rabbitmq版本不匹配 3. 安装目录有空格…

2023国赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

关于git执行提交报错问题

1.在执行git中 执行git init 执行 git add . 执行git commit -m “first commit” 时会出现 git config --global user.email "youexample.com" git config --global user.name "username" 这个问题是由于在git中没有设置默认的user跟emali导致需要手…

SwiftUI 动画进阶:实现行星绕圆周轨道运动

0. 概览 SwiftUI 动画对于优秀 App 可以说是布帛菽粟。利用美妙的动画我们不仅可以活跃界面元素,更可以单独打造出一整套生动有机的世界,激活无限可能。 如上图所示,我们用动画粗略实现了一个小太阳系:8大行星围绕太阳旋转,而卫星们围绕各个行星旋转。 在本篇博文中,您将…