• 学会使用set和map的基本接口


    上一篇笔记记录了二叉搜索树的实现,这一篇笔记介绍的 set 和 map,底层就是由二叉搜索树实现的,我们来学习他们两个的常用接口。

    目录

    set的使用

    set的模板参数

    insert

    erase

    count

    lower_bound

    upper_bound

    multiset

    count

    erase

     find

    键值对

    map

     find

    insert

    make_pair

    insert的返回值

    operator []

    重载 [] 的实现


    set的使用

    set的模板参数

    T: set中存放元素的类型。
    Compare:set中元素默认按照小于来比较
    Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

    insert

    insert是向set里面插入值,因为底层为二叉搜索树,中序遍历一定为有序,并且没有数据冗余,可实现去重的功能:

    erase

    删除某个结点,和find配合使用,

    find返回的是一个迭代器,传迭代器类型进行删除:

    也可以直接传参数进项删除:

    count

    count有计数的意思,在 multi 版本下会返回数据出现的次数,在普通版本下,存在就返回 1 ,不存在返回 0 ,相较于 find ,更加方便查找:

    lower_bound

    返回大于等于参数的位置:

    可以erase的区间删除配合使用

    删除大于等于参数的所有值

    upper_bound

    无论参数是否存在,返回的都是大于参数的位置:

    可以和 lower_bound配合erase使用,删除一个闭区间的数据

    我们传的是一个闭区间,而erase删除的是左闭右开区间,使用upper_bound刚刚好:

    multiset

    允许数据重复的set版本,接口用法几乎完全相同,常用的与set区别开的接口如下:

    count

    计数接口,set版本返回的是0和1,此版本下返回的是数据的个数:

    erase

    删除接口,set版本返回的是0和1,而此版本下删除返回的是删除数据的个数:

     find

    若找的是重复的数据,返回的是中序遍历到的第一个数据的位置:

    键值对

    1. template <class T1, class T2>
    2. struct pair
    3. {
    4. typedef T1 first_type;
    5. typedef T2 second_type;
    6. T1 first;
    7. T2 second;
    8. pair()
    9. : first(T1())
    10. , second(T2())
    11. {}
    12. pair(const T1& a, const T2& b)
    13. : first(a)
    14. , second(b)
    15. {}
    16. };

    是这样一个数据结构,我们可以将它作为二叉搜索树的结点来使用

    一般只包含两个成员变量key和value,key代表键值,
    value表示与key对应的信息

    map

     find

    会返回找到元素的迭代器,pari 数据结构中,key_type元素不允许修改,查找时找的也是key_type元素,而pair 中的第二个元素 value_type 允许修改。

    因为这种性质,我们可以通过查找 key 而找到对应的 value ,并且对 value 进行修改。

    1. void test9()
    2. {
    3. //将以下数据插入map中,并且计数
    4. string arr[] = { "马克杯", "玻璃杯", "塑料杯", "玻璃杯", "玻璃杯", "玻璃杯", "马克杯", "马克杯", "塑料杯", "玻璃杯" };
    5. map<string, int> m;
    6. for (auto& str : arr)
    7. {
    8. map<string, int>::iterator it = m.find(str);
    9. //找到返回的是key_type(即pair的第一个数据)的迭代器
    10. if (it != m.end())
    11. {
    12. it->second++; //找到pair的second( value_type ) 自增 1
    13. }
    14. else //没找到说明没有,则插入
    15. {
    16. m.insert(make_pair(str, 1));
    17. }
    18. }
    19. }

    insert

    插入的一般是一个键值对,目前需要掌握的插入时的键值对构造有三种:

    1. map<int,string> m;
    2. //1. 声明类型,匿名对象
    3. m.insert(pair<int, string>(1, "a"));
    4. //2. 创建对象,插入对象
    5. pair<int, string> kv(2, "b");
    6. m.insert(kv);
    7. //3. 调用函数模板make_pair,不用声明pair类型
    8. m.insert(make_pair(3, "c"));

    make_pair

    insert的返回值

    在上面find中,我们可以通过find对 key 进行查找,并且计数,但是这会有两次重复的查找过程,find先查找一次,insert 时要查找一次对此进行优化:

    不用find ,直接通过 insert 也是可以实现的:

    insert 插入成功后返回的一个pair的类型;

    此pair中的first是插入元素的迭代器,second是bool值;

    插入成功将pair中的second 元素设置为 true,

    如果已存在要插入的key,则将为 pair的second 设置为false。

    相当于返回的是pair,而这里的迭代器是指向的是插入的pair。

    1. //insert 插入计数
    2. void test10()
    3. {
    4. //将以下数据插入map中,并且计数
    5. string arr[] = { "马克杯", "玻璃杯", "塑料杯", "玻璃杯", "玻璃杯", "玻璃杯", "马克杯", "马克杯", "塑料杯", "玻璃杯" };
    6. mapint> m;
    7. for (auto& str : arr)
    8. {
    9. auto ret = m.insert(make_pair(str, 1));
    10. if (ret.second == false)
    11. {
    12. ret.first->second++;
    13. }
    14. }
    15. //遍历
    16. auto it = m.begin();
    17. while (it != m.end())
    18. {
    19. cout << it->first << ":" << it->second << endl;
    20. it++;
    21. }
    22. }

    operator []

    在map中,上述 find 和 insert 实现插入和计数都不算最简便的写法,最牛的写法是重载的 [] :

    重载 [] 的实现

    那么重载的 [] 是怎么样实现的呢:

    为了提高可读性,我们将其展开分析,如下图:

    将上面那一长串展开,我们能清楚的看到,传进来的参数 k ,即 [] 中的 key_type 参数,在进入重载[],后,和用 insert 插入计数的步骤大致相同:

    用 k 和 value 的匿名对象构造pair类型插入到map对象中;

    通过insert的返回值,拿到插入的pair的迭代器,再通过迭代器访问并返回second的引用,最后进行修改。

  • 相关阅读:
    《清单革命》内容梳理&随笔
    写了个工具ArcGIS批量下载影像图!分享给大家
    java的面向对象基础(5)——异常
    Web Speech API-语音合成
    ATFX:美国10月CPI数据来袭,核心通胀能否迎来拐点?
    Transformer、BERT和GPT 自然语言处理领域的重要模型
    【Vue】vue项目用qrcodejs2生成带log的二维码图片,vue生成二维码图片中间带log,自定义log
    Kubernetes(k8s)集群渗透
    UNet pytorch 胎教级介绍 使用DRIVE眼底血管分割数据集进行入门实战
    php初级教程八 Error
  • 原文地址:https://blog.csdn.net/weixin_53316121/article/details/126112701