• 【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构


    💓博主CSDN主页:杭电码农-NEO💓

    ⏩专栏分类:C++从入门到精通

    🚚代码仓库:NEO的学习日记🚚

    🌹关注我🫵带你学习C++
      🔝🔝


    在这里插入图片描述

    1. 前言

    在学习了二叉搜索树后,现在
    就可以来学习map和set了,虽然
    它们的底层是红黑树结构,但是红黑树
    的本质也是一颗二叉搜索树!

    本质重点:

    本篇文章着重讲解map和set的
    使用方法以及一些特性,以及讲解
    muti为前缀的map/set和普通map/set
    的区别,其中会学到一个重要的结构
    pair,它会伴随我们很久


    2. map和set介绍

    set是key模型,本质是确定一个
    元素在不在此容器中,也就是说
    set中存储的是一个单一数据

    map和set的区别就是,map中存储
    的并不是一个单一数据,而是存储了
    一个pair结构!(后面会讲解)

    在这里插入图片描述
    在这里插入图片描述

    map的模板参数中有key和T
    而set的模板参数只有T

    set和map结构中遍历出来是
    数据有序并且去重的!

    map和set都只支持增删查,不支持改!


    3. pair结构介绍

    pair结构实际上是一个键值对
    以下是对于键值对的介绍:

    在这里插入图片描述

    这个类的代码大概是这样的:

    template <class T1, class T2>
    struct pair
    {
    	T1 first;
    	T2 second;
    	pair(): first(T1()), second(T2())
    	{}
    	pair(const T1& a, const T2& b): first(a), second(b)
    	{}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    它实际上就是封装了两个可以是不同
    类型的数,它可以用作中英字典,存储
    pair的结构,first存储中文
    second存储对应的英文解释,非常好用!

    map中存储的就是pair结构,所以
    map也叫存储的KV模型,因为first和
    second对应key和value

    map的三种常见使用方法:

    1. 方法一: 定义pair对象后插入

    map<string,string> dict;
    pair<string,string> kv1("排序","sort");
    pair<string,string> kv2("左边","left");
    dict.insert(kv1);
    dict.insert(kv2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 方法二: 使用匿名对象插入

    map<string,string> dict;
    dict.insert(pair<string,string>("排序","sort"));
    dict.insert(pair<string,string>("左边","left"));
    
    • 1
    • 2
    • 3

    3. 方法三: 使用make_pair插入

    map<string,string> dict;
    dict.insert(make_pair("排序","sort"));
    dict.insert(make_pair("左边","left"));
    
    • 1
    • 2
    • 3

    make_pair是最好用的方法!


    4. set结构详解

    在这里插入图片描述

    先看set的第二个模板参数是less
    是不是很熟悉?set默认情况下遍历
    出来是升序,但是如果定义对象时显示
    传参greater,就是降序!

    set<int,greater<int>> s;
    
    • 1

    set的插入函数insert
    在这里插入图片描述

    插入我们需要关心三点:
    一是插入可以不用写pos,直接插入
    二是可以插入一段迭代器区间
    三是插入的返回值也是一个pair结构
    pair中存储了布尔类型和迭代器,分别
    代表此次插入是否成功,若成功则返回
    被插入元素迭代器的位置

    set的查找和删除函数find,erase
    在这里插入图片描述

    在这里插入图片描述


    5. map结构详解

    在这里插入图片描述

    set是没有支持方括号的
    而map支持了,所以先讲解方括号的使用

    map的方括号用法:
    先看文档:
    在这里插入图片描述
    在这里插入图片描述

    map的方括号设计的十分巧妙
    它的参数的pair中的first,返回值
    是pair中的second,并且它返回的是
    引用,可以根据first修改second
    它可以用来计数,请看如下demo代码:

    统计水果的数量:

    string arr[]={"苹果","西瓜","香蕉","苹果","西瓜","西瓜","西瓜","苹果"};
    map<string,int> countmap;
    for(auto str : arr)
    {
    	countmap[str]++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请再看文档的详细信息:

    在这里插入图片描述

    也就是说,方括号自带插入功能,当
    出现第一个"西瓜"时,会自动把"西瓜"
    插入到map中,第二次遇见"西瓜"时,
    会将西瓜的计数++变成2

    map的删除和查找:
    由于map的插入在前面已经讲解过了
    这里只讲解删除和查找

    在这里插入图片描述
    在这里插入图片描述

    erase和find传参只用传pair中的first
    类型的参数,即可完成任务,并且find的
    返回值和set的find是一样的,一个意思


    6. multimap和multiset

    map和set的遍历是有序并且去重的
    也就是说里面没有相同的元素,但是
    STL提供了multimap和multiset
    它们允许存在相同的元素!

    在这里插入图片描述
    在这里插入图片描述

    由于支持元素冗余
    所以multimap不支持方括号了!

    当我们插入相同的数据时,它也会保存

    在这里插入图片描述


    7. map和set实战演练

    请看下面的力扣题目:

    在这里插入图片描述

    力扣692题

    大家先思考一下对策吧

    题目解析:

    本题目不仅仅要找出前k个高频的单词
    并且还要按照字典序来排序,也就是说,
    要满足两个排序的条件:字符串出现的次数
    和字符串在字典中的顺序!

    想到要计数,当然是用map啦!

    map<string,int> mpcount;
    for(auto str : words)
    	mpcount[str]++;
    
    • 1
    • 2
    • 3

    两个细节问题以及结论

    • map计数后,只需以map中的second
      作为基准来排序即可得到前k个高频

    • map本身的遍历就是有序的,并且此
      顺序刚好是字典序(以first排序的)

    结论:只需使用一个排序算法,在不打乱
    map原本排序的情况下,以map中的
    second为基准排个序,即可得到我们
    想要的答案,所以关键是要使用稳定
    的排序算法!

    库中稳定的排序算法:stable_sort

    在这里插入图片描述

    下面是所有的代码,不懂可以私信我

    class Solution {
    public:
        struct _compare
        {
            bool operator()(pair<string,int> p1,pair<string,int> p2)
            {
                return p1.second>p2.second;
            }
        };
        vector<string> topKFrequent(vector<string>& words, int k) {
            map<string,int> mpcount;
            for(auto str : words)
                mpcount[str]++;
            vector<pair<string,int>> tmp;
            auto it = mpcount.begin();
            while(it!=mpcount.end())
            {
                tmp.push_back(*it);
                it++;
            }
            _compare com;
            vector<string> ret;
            stable_sort(tmp.begin(),tmp.end(),com);
            for(int i=0;i<k;i++)
                ret.push_back(tmp[i].first);
            return ret;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    8. 总结

    熟悉map和set的使用在平常做题
    时会有大用处,虽然平时用的更多的
    是unordered_map/set,但是它们的
    使用方法基本一致,学到就是赚到!


    🔎 下期预告:AVL树深度剖析 🔍
  • 相关阅读:
    最新科技喜报!统一图像和文字生成的MiniGPT-5来了!
    Docker+Jenkins+Harbor+Rancher持续集成部署分布式项目
    NLP算法面经 | 腾讯 VS 美团
    FFmpeg学习笔记汇总
    mmc子系统分析
    CURL简单使用
    408王道操作系统强化——文件管理及大题解构
    B. M-arrays
    TiDB v6.2 发版
    【PLC】三菱plc控件安装 component Movedata had the following error ... Error Number:-119
  • 原文地址:https://blog.csdn.net/m0_61982936/article/details/134365662