【C/C++】学习STL标准模板库 004 map | multimap 容器 快到碗里来(◕ᴗ◕✿)

本文介绍了C++ STL中的map和multimap容器,讲解了pair类模板、map的创建、键值对的获取、数据添加与遍历等操作,并给出了编程实战示例,演示如何使用map统计自然数出现的次数。此外,还对比了map与multimap的区别,强调了multimap允许键值重复的特点及其常用方法。
摘要由CSDN通过智能技术生成

今天的主题是什么?map(映射)!map(映射)!map(映射)!

pair类模板

在开始学习map之前,先来看看pair。考虑到“键值对”并不是普通的类型数据,C++ STL标准库提供了pair类模板,专门用来将2个普通元素first和second(可以是任何已有的数据类型)创建成1个新元素<first, second>. 通过其构成的元素格式不难看出,使用pair类模板来创建“键值对”形成的元素非常合适。使用pair类模板需要增加头文件【#include <pair>】

 pair的使用

// 创建一个空的pair对象p
pair<int, string> p;
// 创建一个空的pair对象p2并赋值(2022, "BigXMeng")
pair<int, string> p2(2022, "BigXMeng");
// 创建一个和p2一模一样的pair对象
pair<int, string> p3(p2);
// 使用make_pair()函数创建一个pair对象
pair<int, string> p4(make_pair(2022, "Liu Xianmeng"));
printf("%d %s\n", p.first, &p.second[0]);
printf("%d %s\n", p2.first, &p2.second[0]);
printf("%d %s\n", p3.first, &p3.second[0]);
printf("%d %s\n", p4.first, &p4.second[0]);
printf("p2 == p3 ? ");
if(p2 == p3) printf("true\n");
else printf("false\n");

map

 map概述

  • map容器存储的都是pair对象,也就是用pair类模板创建的键值对。其中,各个键值对的键和值可以是任意的数据类型,包括C++基本数据类型(int、double等)、结构体或自定义类型。通常情况下,map容器中存储的各个键值对都选用string字符串作为键的类型。在使用map容器存储多个键值对的时候,会自动根据键值对中键的大小按照既定的规则进行排序。需要注意的是,使用map容器存储的各个键值对,键的值既不能重复也不能被修改。
  • 使用map容器需要添加头文件【#include <map>】

 创建map对象

// 创建一个空的map容器
map<string, char> m;
// 创建map容器的同时进行初始化数据
map<string, char> m2{{"BigXMeng", 'M'},{"zhangsan", 'F'}};
// 效果和m2的创建是一样的
map<string, char> m3{make_pair("BigXMeng", 'M'), make_pair("lisi", 'F')};
// 创建一个和m2数据完全一样的map
map<string, char> m4(m2);

 验证map对存储的数据的排序(按照键的大小)

 用map获取键值对的方法

map容器中存储的都是pair类型的键值对,在实际使用中map容器的场景中,经常要做的不是找到指定的键值对【pair对象】,而是从map中找到某个键对应的值。map容器提供了以下2种方法,可以直接获取map容器键指定的值:(1) m.[KEY]   (2) m.at(KEY)

map<string, char> m{{"BigXMeng", 'M'},{"zhangsan", 'F'}};
char receive = m["BigXMeng"];
char receive2 = m.at("BigXMeng");
printf("char receive = %c\n", receive); // char receive = M
printf("char receive2 = %c", receive2); // char receive2 = M

 添加数据和遍历数据

map<char, string> m;
m.insert(make_pair('f', "I ")); // 可以插入一个pair
// 可以插入一个存储pair的list
m.insert({make_pair('o', "enjoy "),make_pair('q', "learning ")});
m.insert({'a', "STL ~"}); // 可以插入一个二维空间
map<char,string> :: iterator it;
int i;
for(it=m.begin(), i=1; it!=m.end(); ++it,++i){
    printf("pair%d : <\'%c\', \"%s\">\n", i, it->first, &it->second[0]);
    /** [遍历结果如下]
     *  pair1 : <'a', "STL ~">
     *  pair2 : <'f', "I ">
     *  pair3 : <'o', "enjoy ">
     *  pair4 : <'q', "learning ">
     */
}

 其他操作演示

printf("1 当前的map的size = %d\n", m.size());
printf("2 当前的map是否为空 = %s\n", m.empty()?"Yes":"No");
auto p1 = m.upper_bound('a'); // 返回第一个key大于'a'的pair迭代器
auto p2 = m.lower_bound('a'); // 返回第一个key大于或等于'a'的pair迭代器
printf("3 p1 = <\'%c\', \"%s\">\n", p1->first, &p1->second[0]);
printf("4 p2 = <\'%c\', \"%s\">\n", p2->first, &p2->second[0]);
m.clear(); // 清空map
printf("5 当前的map是否为空 = %s\n", m.empty()?"Yes":"No");
/** [打印结果如下]
 * 1 当前的map的size = 3
 * 2 当前的map是否为空 = No
 * 3 p1 = <'o', "enjoy ">
 * 4 p2 = <'a', "STL ~">
 * 5 当前的map是否为空 = Yes
 */

multimap

multimap 概述

  • multimap相比于map可以存储多个键相同的键值对,正因如此,mutilmap不支持这两种方法取数据: (1) m.[KEY]   (2) m.at(KEY)  ;同时lower_bound(KEY)、upper_bound(KEY)、count(KEY)等方法比较常用
  • 使用multimap需要包含头文件【#include <map>】

m.equal_range(val) 函数

multimap中可以插入相同的键,那么我们如何得知插入了多少个键值相同的元素呢?这个时候m.equal_range(val) 函数闪亮登场,它会返回一个pair类型的迭代器,其中的first指向包含val的所有元素范围的左边界,而second指向右边界。

一起来验证一下:

#include <bits/stdc++.h>
using namespace std;
int main(){
    multimap<int, string> m;
    m.insert(make_pair(8, "Big"));
    m.insert(make_pair(6, "X1"));
    m.insert(make_pair(6, "X2"));
    m.insert(make_pair(2, "Meng"));
    m.insert(make_pair(6, "X3"));
    pair<multimap<int, string>::iterator, multimap<int, string>::iterator> pair = m.equal_range(6);
    int i = 1;
    for(multimap<int, string> :: iterator it = pair.first; it!=pair.second; ++it, ++i){
        printf("第%d个键为6的m中的元素为:<%d, \"%s\">\n", i, it->first, &it->second[0]);
    }
    /* [打印遍历结果]
       第1个键为6的m中的元素为:<6, "X1">
       第2个键为6的m中的元素为:<6, "X2">
       第3个键为6的m中的元素为:<6, "X3">
     */
    printf("断点调式..");
    return 0;
}

 其他通用操作后续更新...

    编程实战 

问题 1: 统计数字

题目描述

(时间限制: 1.000 Sec  内存限制: 64 MB)

某次科研调查时得到了n个自然数,每个数均不超过1500000000 (1.5×109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。

输入

第1行是整数n,表示自然数的个数;
第2~n+1每行一个自然数。

输出

共m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。

样例输入 Copy

8
2
4
2
4
5
100
2
100

样例输出 Copy

2 3
4 2
5 1
100 2

提示

100%的数据满足:1≤n≤200000,每个数均不超过1.5×109。

问题分析和代码:

/**
 * Created By Liu Xianmeng On 2022/11/30
 * 【题目分析】
 * 题目要求需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果
 * 而 C++ STL的 map集合几乎可以完美地解决这个问题
 * 当遍历到一个要记录的数,这个数在map中不存在时,则新建一个pair存入map
 * 若map中已经存在该数的记录信息 则将返回的迭代器指向的pair的值+1
 */
#include <bits/stdc++.h>
using namespace std;
int main(){
    int n;
    scanf("%d", &n);
    map<int, int> m; // 用map存要打印的数据
    int num;
    // 循环输入要记录的数字num
    for(int i=1; i<=n; ++i){
        scanf("%d", &num);
        // 如果map中目前没有num的保存信息
        if(m.find(num) == m.end()){
            // 则新建一个pair并放入map
            m.insert(make_pair(num, 1));
        } else{ // 如果map中已经有num的保存信息
            ++(m.find(num)->second); // 则将找到的返回的迭代器指向的pair的值+1
        }
    }
    // 打印结果
    for(auto p : m){
        printf("%d %d\n", p.first, p.second);
    }
    return 0;
}

 

谢谢读取 ~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值