C++容器map的常见用法

文章目录

      • 1.map和multimap容器
        • 1.map容器的构造和赋值
          • 1.构造函数
          • 2.赋值操作
        • 2.map容器的大小和交换
          • 1.获取大小
          • 2.交换内容
        • 3.map容器的插入和删除
          • 1.插入元素
          • 2.删除元素
          • 3.注意事项
        • 4.map容器的查找和统计
          • 1.查找元素
          • 2.统计元素
          • 3.示例
        • 5.map容器的排序
          • 1.自定义排序规则
          • 2.注意点
          • 3.示例:基于value排序

1.map和multimap容器

在C++ STL(标准模板库)中,mapmultimap是两种关联容器,它们用于存储键值对,其中每个键都是唯一的,并且与一个特定的值相关联。然而,它们之间存在一些关键区别:

map

  1. 唯一性map中的键是唯一的,也就是说,一个键只能对应一个值。如果你尝试插入一个键值对,而该键已经存在于map中,那么原有的键对应的值将被新值替换。

  2. 排序map中的元素按照键的升序(默认情况下)进行排序。这是通过比较键实现的,可以自定义比较函数来改变排序方式。

  3. 基本操作:主要操作包括插入(insert)、删除(erase)、查找(find)和访问(直接通过键访问,如map[key])元素。

multimap

  1. 非唯一性:与map的主要区别在于,multimap允许有多个相同的键,每个键可以对应多个不同的值。这意味着当你插入一个键已经存在的键值对时,新值会被添加到该键已有的值集合中,而不是替换原有值。

  2. 排序:和map一样,multimap中的元素也是根据键进行排序的,可以是升序或根据自定义的比较函数排序。

  3. 基本操作:除了与map共享的基本操作外,由于可能有多个相同键的存在,multimap的查找操作(如find)可能会返回一个迭代器范围,表示所有匹配键的值集合。

使用场景

  • map适用于当你需要确保每个键只对应一个值,且经常需要根据键快速查找或更新其关联值的场景。

  • multimap适合那些一个键可能对应多个值,且在查询时你可能关心所有与某一键相关联的值的情况,比如存储学生的分数时,如果有多个学生获得相同的分数,multimap能很好地处理这种情况。

1.map容器的构造和赋值

在C++中,std::map容器提供了多种构造函数和赋值操作,以方便初始化和管理键值对数据。

1.构造函数
  1. 默认构造函数

    std::map<Key, T> m; // 创建一个空的map,默认按键升序排序。
    
  2. 拷贝构造函数

    std::map<Key, T> m1;
    // 假设m1已经被初始化
    std::map<Key, T> m2(m1); // m2是m1的一个拷贝
    
  3. 使用比较函数构造

    struct MyCompare {bool operator()(const Key& lhs, const Key& rhs) const {// 自定义比较逻辑return lhs < rhs; // 示例:使用默认比较}
    };
    std::map<Key, T, MyCompare> m(MyCompare()); // 使用自定义比较函数
    
  4. 区间构造

    std::map<Key, T> m.begin(), m.end());
    // 或者使用其他容器/迭代器范围
    std::vector<std::pair<Key, T>> vec;
    // 假设vec已被填充
    std::map<Key, T> m(vec.begin(), vec.end());
    
2.赋值操作
  1. 拷贝赋值运算符

    std::map<Key, T> m1, m2;
    // 假设m1和m2已经被初始化
    m1 = m2; // 将m2的内容赋值给m1
    
  2. 初始化列表赋值(C++11及以上)

    std::map<Key, T> m = { {key1, value1}, {key2, value2}, ... };
    
  3. 区间赋值

    std::map<Key, T> m1, m2;
    // 假设m2已被填充
    m1.assign(m2.begin(), m2.end());
    
  4. 插入迭代器对
    虽然这不是直接的赋值操作,但可以通过迭代器对插入元素来“赋值”或填充map。

    std::map<Key, T> m;
    std::vector<std::pair<Key, T>> vec;
    // 假设vec已被填充
    m.insert(vec.begin(), vec.end());
    

这些构造和赋值方法提供了灵活的方式来创建和管理std::map容器,满足不同场景下的需求。

 ```cpp#include <iostream>#include <map>// 使用标准命名空间,简化后续代码中的类型名称using namespace std;/*** 打印map的内容* @param m 一个整数到整数的映射,其内容将被打印*/void printMap(const map<int,int>& m){// 遍历映射中的所有元素,并打印每个元素的键和值for(auto it : m){cout << it.first << " " << it.second << endl;}}int main(){// 初始化一个map,包含两个元素map<int,int> m = {{1,2},{2,4}};// 创建一个对m的常量引用,以避免复制map的内容const map<int,int>& m1(m);// 调用函数打印map的内容printMap(m);printMap(m1);// 初始化一个空的map,并将其设置为与m相同的内容map<int,int> m2;m2 = m;printMap(m2);return 0;}```
2.map容器的大小和交换

在C++的STL中,std::map容器提供了以下与大小和交换相关的成员函数:

1.获取大小
  • size(): 此函数返回map中元素的数量,即键值对的总数。

    std::map<Key, T> myMap;
    // ... 添加元素到myMap
    std::cout << "Size of the map: " << myMap.size() << std::endl;
    
  • empty(): 判断map是否为空,如果容器中没有元素,则返回true,否则返回false

    if (myMap.empty()) {std::cout << "The map is empty." << std::endl;
    } else {std::cout << "The map is not empty." << std::endl;
    }
    
2.交换内容
  • swap(std::map<Key, T>& other): 此函数交换两个map容器的内容,交换操作高效执行,不会涉及元素的复制或移动。

    std::map<Key, T> myMap1, myMap2;
    // ... 分别填充myMap1和myMap2
    myMap1.swap(myMap2);
    // 现在myMap1包含myMap2原来的内容,反之亦然
    

这些函数允许检查容器的当前状态(是否为空,包含多少元素)以及重新分配两个容器的内容,而无需创建新的容器副本。这对于优化内存使用和性能特别有用。

//
// Created by 86189 on 2024/7/3.
//
#include <iostream>
#include <map>// 使用标准命名空间,简化后续代码中标准库类型的引用
using namespace std;/*** 打印map的内容* @param m 一个整数到整数的映射,其内容将被打印*/
void printMap(const map<int,int>& m){// 遍历map,打印每个键值对for(auto it : m){cout << it.first << " " << it.second << endl;}
}int main(){// 初始化一个map,包含两个元素map<int,int> m{{1,2},{2,4}};// 调用函数打印map内容printMap(m);// 打印map的大小cout << m.size() << endl;// 检查map是否为空,如果不为空,则再次打印其内容if(!m.empty()){printMap(m);}// 初始化另一个空的mapmap<int,int> m1;// 交换两个map的内容m.swap(m1);// 分别打印交换后的两个map的内容printMap(m);printMap(m1);return 0;
}
3.map容器的插入和删除

在C++的STL中,std::map容器提供了丰富的成员函数来进行元素的插入和删除操作。以下是几种常见的插入和删除方法:

1.插入元素
  1. insert(const value_type& val): 插入一个键值对。如果键已存在,则不会插入重复的键。

    myMap.insert(std::make_pair(key, value));
    // 或者使用直接初始化语法(C++11起)
    myMap.insert({key, value});
    
  2. insert(iterator hint, const value_type& val): 尝试在迭代器hint指向的位置附近插入元素,以提高效率。如果hint恰好指向要插入位置的下一个位置,则插入操作可能更快。

    auto it = myMap.lower_bound(key);
    myMap.insert(it, std::make_pair(key, value));
    
  3. insert(initializer_list<value_type> ilist): 从初始化列表插入多个键值对(C++11起)。

    myMap.insert({ {key1, value1}, {key2, value2}, ... });
    
2.删除元素
  1. erase(iterator position): 删除迭代器position指向的元素。

    auto it = myMap.find(key);
    if (it != myMap.end()) {myMap.erase(it);
    }
    
  2. erase(const key_type& key): 删除具有指定键的元素。

    myMap.erase(key);
    
  3. erase(iterator first, iterator last): 删除迭代器范围[first, last)内的所有元素。

    auto startIt = myMap.lower_bound(startKey);
    auto endIt = myMap.upper_bound(endKey);
    myMap.erase(startIt, endIt);
    
3.注意事项
  • 在删除元素后,之前指向被删除元素的迭代器、指针和引用都会变得无效。
  • erase返回的是下一个元素的迭代器,这在连续删除元素时很有用。
  • 对于insert操作,如果试图插入的键已经存在,该操作不会改变容器且不会抛出异常(除非因内存分配失败)。

通过这些方法,你可以有效地管理std::map容器中的数据,无论是添加新元素还是移除不需要的条目。

//
// Created by 86189 on 2024/7/3.
//
#include <iostream>
#include <map>// 使用标准命名空间,简化后续代码中标准库类型的引用
using namespace std;/*** 打印map的内容* @param m 一个整数到整数的映射,其内容将被打印*/
void printMap(const map<int,int>& m){// 遍历map,打印每个键值对for(auto it : m){cout << it.first << " " << it.second << endl;}
}int main(){// 初始化一个map,包含两个元素map<int,int> m{{1,2},{2,4}};// 调用函数打印map内容printMap(m);// 打印map的大小cout << m.size() << endl;// 检查map是否为空,如果不为空,则再次打印其内容if(!m.empty()){printMap(m);}// 初始化另一个空的mapmap<int,int> m1;// 交换两个map的内容m.swap(m1);// 分别打印交换后的两个map的内容printMap(m);printMap(m1);return 0;
}
4.map容器的查找和统计

在C++的STL中,std::map容器提供了几种查找和统计元素的方法:

1.查找元素
  1. find(const key_type& k): 返回一个迭代器,指向键为k的第一个元素。如果找不到这样的元素,则返回end()

    auto it = myMap.find(key);
    if (it != myMap.end()) {std::cout << "Found element with key: " << it->first << ", value: " << it->second << std::endl;
    } else {std::cout << "Element not found." << std::endl;
    }
    
  2. count(const key_type& k): 返回键为k的元素数量。对于map,由于键唯一,此函数要么返回0(表示不存在),要么返回1(表示存在)。

    size_t count = myMap.count(key);
    if (count > 0) {std::cout << "Key exists in the map." << std::endl;
    } else {std::cout << "Key does not exist in the map." << std::endl;
    }
    
2.统计元素

map容器中,由于键的唯一性,统计通常较为直接,主要依赖于count函数来确定某个键是否存在。对于键值对的计数,通常意义不大,因为每个键最多只能对应一个值。但在多值映射multimap中,count可以有效统计相同键值出现的次数。

3.示例

假设有一个std::map<int, std::string>类型的myMap,以下是如何使用查找和统计方法的简单示例:

#include <iostream>
#include <map>// 使用标准命名空间,简化后续代码中标准库的调用
using namespace std;/*** 打印map中的所有元素* @param m 一个整数到整数的映射,其元素将被打印*/
void printMap(const map<int,int>& m){// 遍历map中的每个元素,并打印其键值对for(auto it : m){cout << it.first << " " << it.second << endl;}
}int main(){// 初始化一个map,包含两个元素:{1, 2} 和 {2, 4}map<int,int> m{{1,2},{2,4}};// 寻找键值为1的元素auto it = m.find(1);cout << it->first << endl;// 检查是否找到键值为1的元素if(it != m.end()){cout << "in" << endl;} else{cout << "no" << endl;}// 调用函数打印map的所有元素printMap(m);// 打印键值为1的元素在map中出现的次数cout << m.count(1) << endl;return 0;
}
5.map容器的排序

std::map容器在C++ STL中自动保持其元素有序。默认情况下,元素是按照键(key)的升序进行排序的。这种排序是由比较函数决定的,std::map默认使用std::less<Key>作为比较器,它提供了一个严格弱序的比较,适用于大多数基本数据类型。

1.自定义排序规则

尽管std::map默认按key排序,但如果你想改变排序逻辑,可以在创建map时指定一个自定义的比较函数对象。例如,如果你想让map按照key降序排列,或者基于键的某些复杂属性排序,你可以这样做:

struct CustomCompare {bool operator()(const Key& lhs, const Key& rhs) const {// 自定义比较逻辑,例如降序排序:return rhs < lhs; // 改变比较逻辑以实现降序}
};std::map<Key, Value, CustomCompare> myMap;
2.注意点
  • 不可更改排序:一旦map实例化,其排序规则就不能再改变。如果需要改变排序,你需要创建一个新的map实例并使用不同的比较函数。
  • 基于value排序:如果需要按照value排序,std::map本身不直接支持。一个常见做法是将map的元素复制到一个std::vector中,每个元素是一个键值对(例如,使用std::pair<Key, Value>),然后对这个vector进行排序。可以使用std::sort函数配合自定义的比较器来达到目的。
3.示例:基于value排序
std::map<Key, Value> originalMap;
// ... 填充originalMapstd::vector<std::pair<Key, Value>> items(originalMap.begin(), originalMap.end());
std::sort(items.begin(), items.end(), [](const std::pair<Key, Value>& a, const std::pair<Key, Value>& b) {return a.second > b.second; // 降序排序基于value
});// 现在items是按value排序的键值对集合

综上所述,虽然std::map自动维持其内部元素的排序(基于键),但通过自定义比较函数,可以控制排序逻辑。而对于基于value的排序,则需借助额外的数据结构和排序算法。

//
// Created by 86189 on 2024/7/3.
//
#include <iostream>
#include <map>
using namespace std;// 自定义比较函数对象,用于map中键值的降序排序
class Compare{
public:// 比较两个整数,返回true如果第一个大于第二个bool operator()(const int &a,const int &b) const{return a > b;}
};// 打印map中的所有元素
// 参数m: 使用自定义比较函数对象Compare的map
void printMap(const map<int, int, Compare>& m){// 遍历map中的每个元素并打印for(auto it : m){cout << it.first << " " << it.second <<endl;}
}int main(){// 初始化一个使用自定义比较函数对象的mapmap<int,int,Compare>m{{1,2},{2,4},{3,5}};// 调用函数打印map内容printMap(m);return 0;
}

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

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

相关文章

责任链模式在金融业务中的应用及其框架实现

引言 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;它通过为请求创建一个处理链&#xff0c;使多个对象都有机会处理这个请求。责任链模式通过将请求的发送者和接收者解耦&#xff0c;使得多个接收者可以依次处理请求&am…

Linux——命令执行原理,命令别名

### 执行原理 - 系统为了让用户在命令行快速方便地执行命令&#xff0c;将可执行文件的路径存储在环境变量PATH中&#xff0c;使得shell知道命令的可执行文件位置 - PATH环境变量&#xff1a;当用户每次执行外部命令的时候都会去该变量所记录的路径下搜索和命令同名的二进制文件…

景区智慧公厕解决方案,公厕革命新方式

在智慧旅游的浪潮下&#xff0c;景区智慧公厕解决方案正悄然引领着一场公厕革命&#xff0c;不仅革新了传统公厕的管理模式&#xff0c;更以智能化、人性化的服务理念&#xff0c;为游客提供了前所未有的舒适体验。作为智慧城市建设的重要一环&#xff0c;智慧公厕解决方案正逐…

计算机网络之以太网

上文内容&#xff1a;总线局域网以及冲突的解决方法 1.以太网的起源 1.1起源 60年代末期&#xff0c;夏威夷大学Norman Abramson等研制ALOHA无线网络系统,实现Oahu岛上的主机和其它岛及船上的读卡机和终端通信&#xff1b; 出境信道地址&#xff1a;主机到终端&#xff1…

如何利用好用便签提高工作效率?

在忙碌的工作中&#xff0c;我们经常需要记住许多琐碎的任务。如果这些任务被遗忘&#xff0c;可能会对我们的工作产生影响。这时&#xff0c;便签就成为了我们的得力助手。通过合理的使用和管理&#xff0c;便签不仅能帮助我们记住重要的事项&#xff0c;还能提高我们的工作效…

RPM方式安装mysql

下载离线版本mysql。 mysql-5.7.33-1.el7.x86_64.rpm-bundle.tar 解压 26468960 Dec 11 2020 mysql-community-client-5.7.33-1.el7.x86_64.rpm315280 Dec 11 2020 mysql-community-common-5.7.33-1.el7.x86_64.rpm3918736 Dec 11 2020 mysql-community-devel-5.7.33-1.el…

Redis基础教程(十四):Redis连接

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

通过装饰器将有BUG的pytorch算子放置在CPU上,而不用修改模型代码

通过装饰器将有BUG的pytorch算子放置在CPU上,而不用修改模型代码 1.代码 某些pytorch算子发下到设备后会导致设备异常,为了暂时规避,先放在CPU上执行 修改模型源码很不友好,可以采用以下方法 1.代码 def force_cpu(func):def wrapper(self, *args, **kwargs):self_cpu self.…

在Windows可以如此丝滑的测试ios应用

在没有Mac本的时候,又想测试iphone或者ipad该怎么办? 最简单的办法当然是买一个了,如果经济上觉得不划算的话,不妨看看这篇文章,或许能帮到您,有任何问题欢迎一起交流。 原理图 开发环境 操作系统:Windows11 被测设备: iPad mini 15.5 注意事项 一定要安装iTunes!一…

NET程序开发可能会用到的一些资料文档

NET程序开发使用的一些资料文件&#xff0c;NET高级调试&#xff0c;NET关键技术深入解析&#xff0c;WPF专业编程指南&#xff0c;程序员求职攻略&#xff0c;WPF编程宝典等。 下载链接&#xff1a;https://download.csdn.net/download/qq_43307934/89518582

GPT-4o将改变论文学术文风,科学家揭示5年内百万篇论文“is”“are”词频减少10%!

在最近的一项研究中&#xff0c;意大利国际高等研究院&#xff08;SISSA&#xff09;的博士生耿明萌量化了 ChatGPT 对学术论文写作的影响。 与以往主要分析 ChatGPT 生成的段落或文章不同&#xff0c;这次研究更关注整体情况。 论文地址&#xff1a;https://arxiv.org/pdf/2…

如何在Vue中添加事件监听器

在Vue中添加事件监听器主要有两种方式&#xff1a;在模板中直接添加和使用Vue实例的方法。以下将详细解释这两种方法。 1. 在模板中直接添加 在Vue的模板中&#xff0c;你可以直接在HTML元素上使用v-on指令&#xff08;或其简写形式&#xff09;来监听DOM事件&#xff0c;并在…

SpringBoot怎么单独关闭某个类打印出来的日志?

application.yml文件增加以下内容&#xff1a; logging:level:org.springframework.amgp.rabbit: OFF 配置logging:level是配置的什么&#xff1f; 在application.yml文件中配置logging.level是用来设置日志级别的。这是Spring Boot应用中的一个常用配置&#xff0c;它允许您…

go内存返还系统相关代码

在go中内存返还系统相关代码主要由sysUnusedOS实现 在Linux中默认是通过madvice方法的_MADV_FREE进行释放&#xff0c;在这种释放中内存其实是被延迟回收的。 func sysUnusedOS(v unsafe.Pointer, n uintptr) {if uintptr(v)&(physPageSize-1) ! 0 || n&(physPageSiz…

Spring AOP实现操作日志记录示例

1. 准备工作 项目环境&#xff1a;jdk8springboot2.6.13mysql8 1.1 MySQL表 /*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50730Source Host : 127.0.0.1:3306Source Schema …

双扩散金属氧化物半导体(DMOS)应用广泛 超结VDMOS市场需求空间大

双扩散金属氧化物半导体&#xff08;DMOS&#xff09;应用广泛 超结VDMOS市场需求空间大 双扩散金属氧化物半导体简称DMOS&#xff0c;是MOS管的一种。MOS管全称为金属氧化物半导体场效应管&#xff0c;又称为MOSFET&#xff0c;是一种利用改变电压来控制电流的半导体器件。  …

《梦醒蝶飞:释放Excel函数与公式的力量》8.8 STDEVP函数

8.8 STDEVP函数 STDEVP函数是Excel中用于计算总体数据的标准偏差的函数。标准偏差是统计学中的一个重要指标&#xff0c;用于衡量数据集中各数值偏离平均值的程度。总体标准偏差考虑了整个数据集&#xff0c;而不是样本。 8.8.1 函数简介 STDEVP函数用于返回总体数据的标准偏…

2023年工作回顾与总结

一、工作概述 主要工作职责和任务 完善XXX平台的基础能力优化XXX平台基础架构负责平台小组代码评审负责复杂功能的提供技术支持负责复杂功能的技术方案评审负责XXX国家项目中平台相关项目通过验收 具体内容和完成情况 XX平台架构优化 &#xff08;1&#xff09;完成通用控…

Redis 中的通用命令(命令的返回值、复杂度、注意事项及操作演示)

Redis 中的通用命令(高频率操作) 文章目录 Redis 中的通用命令(高频率操作)Redis 的数据类型redis-cli 命令Keys 命令Exists 命令Expire 命令Ttl 命令Type命令 Redis 的数据类型 Redis 支持多种数据类型&#xff0c;整体来说&#xff0c;Redis 是一个键值对结构的&#xff0c;…

第N7周:seq2seq翻译实战-pytorch复现-小白版

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 理论基础 seq2seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于机器翻译、文本摘要等序列转换任务的框架。它由两个主要的递归神经网络&#…