【C++】map 和 set 的使用

news2024/11/15 15:36:02

目录

C++中的键值对

关联式容器

set、multiset

map、multimap


STL的容器分为两类:序列是容器、关联式容器;序列式容器是线性的数据结构,只有存储元素的功能,且像vector、list等还可以指定插入位置;而关联式容器底层底层的数据结构是较高级的红黑树、哈希表等,里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高,但是数据的插入不能像vector那样指定插入位置,它底层有自己的插入逻辑,这样才来保证高效的数据检索能力。

C++中的键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;

pair()
    : first(T1())
    , second(T2())
{}

pair(const T1& a, const T2& b): first(a), second(b)
{}
};

关联式容器

根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层数据结构,容器中的元素是一个有序的序列。今天具体学习树形结构的关联式容器的使用。

set、multiset

两个都属于key的搜索模型,虽然底层也是存储<value, value>构成的键值对,底层使用红黑树实现;set中插入元素时,只需要插入value即可,不需要构造键值对;元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

区别在于,key不允许key冗余,而multikey允许

set的构造:

测试代码:

//set:key搜索模型
 void test_set1()
 {
     //功能:查找在不在
     //增、删、查;  set不支持修改
     set<int> s;
     s.insert(5);
     s.insert(2);
     s.insert(6);
     s.insert(1);
     s.insert(1);
     s.insert(1);
     pair<set<int>::iterator,bool> ret = s.insert(1);
     cout << ret.second << endl;

     set<int>::iterator it = s.begin();
     //中序遍历 底层是红黑树(前提是BST)
     while (it != s.end())
     {
         cout << *it << " ";
         ++it;
     }
     cout << endl;

     //用值删除
     s.erase(2);
     s.erase(20);//删除不存在的,无影响

     //用迭代器删除
     //找不到返回end
     set<int>::iterator it1 = s.find(3);
     //用迭代器时,不能删除不存在的
     if (it1 != s.end())
     {
         s.erase(it1);
     }

     for (auto e : s)
     {
         cout << e << " ";
     }
     cout << endl;

     if (s.count(3))
     {
         cout << "3在" << endl;
     }
     else
     {
         cout << "3不在" << endl;
     }
 }

 void test_set2()
 {
     set<int> s;
     set<int>::iterator itlow, itup;

     for (int i = 1; i <= 10; i++)
     {
         s.insert(i * 10);
     }

     //用法:删除区间[itlow,itup]
     itlow = s.lower_bound(25);//返回 >= val值的第一个迭代器
     itup = s.upper_bound(70);//返回 > val值的第一个迭代器

     s.erase(itlow, itup);
     for (auto e : s)
     {
         cout << e << " ";
     }
     cout << endl;

 }


 //multiset:变异的搜索树,允许相同值插入
 void test_set3()
 {
     //功能:查找在不在
      //增、删、查;  不支持修改
     multiset<int> s;
     s.insert(5);
     s.insert(2);
     s.insert(2);
     s.insert(6);
     s.insert(1);
     s.insert(1);
     s.insert(1);
     s.insert(1);
     s.insert(1);
     s.insert(1);

     for (auto e : s)
     {
         cout << e << " ";
     }
     cout << endl;

     //如果有多个值,find返回的是中序的第一个val的迭代器
     auto it = s.find(1);
     while (it != s.begin())
     {
         cout << *it << " ";
         ++it;
     }

     //[>= val, > val) 等到等于val的区间
     pair<multiset<int>::iterator, multiset<int>::iterator> ret = s.equal_range(1);
     //删除所有等于val的值
     s.erase(ret.first, ret.second);
     size_t count = s.erase(2);

     for (auto e : s)
     {
         cout << e << " ";
     }
     cout << endl;
    
 }

map、multimap

底层数据结构也是红黑树(平衡二叉树),在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair;

map不允许key冗余、支持下标访问符,即在[]中放入key,就可以找到与key对应的value;而multimap不支持下标访问,但允许key冗余。

map的构造:

测试代码:


 //map:key-value搜索模型
 void test_map1()
 {
     map<string,string> dict;
     //pair内部的一个构造是函数模板
     //插入的是一个pair对象
     dict.insert(pair<string, string>("sort", "排序"));
     dict.insert(pair<string, string>("insert", "插入"));
     dict.insert(pair<const char*, const char*>("lest", "左边"));

     string s1("xxx"), s2("yyy");
     dict.insert(make_pair(s1, s2));

     //常用;pair<const char*,const char*> 通过pair的模板构造自动推演参数类型,转换为pair<const string,string>
     dict.insert(make_pair("right", "右边"));

     //[]功能:插入、查找、修改val
     dict["erase"];//插入
     cout << dict["erase"] << endl;//查找
     dict["erase"] = "删除";//修改val
     dict["test"] = "测试";
     dict["left"] = "左边、剩余";
   
     map<string, string>::iterator it = dict.begin();
     while (it != dict.end())
     {
         //pair<string,string>为自定义类型,访问可以用*,也可以用-> 
         cout << (*it).first << "\t" << it->second << endl;
         ++it;
     }
     cout << endl;

     //加上引用,避免深拷贝引起性能消耗
     for (auto& kv : dict)
     {
         cout << kv.first << "\t" << kv.second << endl;
     }
 }

 //统计次数
 void test_map2()
 {
     string arr[] = { "苹果","苹果","苹果","香蕉","栗子"};
     map<string, int> countMap;

     for (auto& str : arr)
     {
         //以前的方式 && multimap的方式
         /*auto ret = countMap.find(str);
         if (ret == countMap.end())
         {
             countMap.insert(make_pair(str, 1));
         }
         else
         {
             ret->second++;
         }*/

         //更优雅的方式
         countMap[str]++;
     }

     for (auto& kv : countMap)
     {
         cout << kv.first << "\t" << kv.second << endl;
     }
 }

 //multimap 允许key冗余,不支持[],其余和map一样

其中,map的下标访问,底层是调用了insert

把文档里的代码拆解:

V& operator[](K& key)
{
    //[]重载函数中,先调用insert,返回了pair<iterator,bool>类型的迭代器
    //如果原来有元素,则插入失败,<指向原有元素的的迭代器,false>
    //如果插入新元素,则插入成功,<指向key的迭代器,true>
    pair<iterator,bool> ret =  insert(make_pair(key, V));
    //ret.first为pair<K,V>类型的迭代器,返回迭代器的val
    return ret.first->second;

}

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

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

相关文章

C++核心编程之---类和对象---C++对象模型和this指针

目录 一、成员变量和成员函数分开存储 二、this指针 三、空指针访问成员函数 四、const修饰成员函数 常函数&#xff1a; 常对象&#xff1a; 一、成员变量和成员函数分开存储 在C中&#xff0c;类内的成员变量和成员分开存储 只有非静态成员变量才属于类的对象上 示例&…

计算机基础知识42

标签的分类和嵌套 1. 单标签&#xff1a; img br hr # <img /> 2. 双标签&#xff1a; a h p div # <a></a> 3. 按照标签属性分类&#xff1a; 块儿标签&#xff1a; 自己独自占一行 # h1-h6 p div 行内(内联)…

2023高德地图poi资源下载

全国8千万地图poi地图数据&#xff1a;含名称、地址、电话、省份、城市、区县、经纬度、电话等信息

笔记47:FCN网络的Pytorch实现

本地笔记地址&#xff1a;D:\work_file\DeepLearning_Learning\03_个人笔记\1.语义分割任务\Pytorch中FCN的实现 a a a

数据结构——线性表②(链表)

《数据结构——线性表①&#xff08;顺序表&#xff09;》一文中已经讲了线性表顺序存储–顺序表相关内容&#xff0c; 这篇文章一起来学习 线性表的链式存储–链表↓↓↓↓↓ 一、链表的定义 线性表的链式存储称为链表&#xff0c;那什么是链式存储呢 其实理解起来就和火车差…

Jetpack:023-Jetpack中的事件二

文章目录 1. 知识回顾2. 使用方法2.1 单击事件2.2 双击事件2.3 长按事件2.4 滑动事件 3. 示例代码4. 内容总结 我们在上一章回中介绍了 Jetpack中事件相关的内容&#xff0c;本章回中继续介绍这方面的内容。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01;…

【Java数据结构重点知识】第一节:认识数据结构与算法、集合框架

一&#xff1a;数据结构与算法 1.数据结构 数据结构是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的数据元素的集合 2.算法 算法就是定义良好的计算过程。他取一个或一组的值为输入&#xff0c;并产生一个或一组作为输出。简单来说就是一系列的…

Linux】centos安装配置及远程连接工具的使用

【Linux】centos安装配置及远程连接工具的使用 1.使用vmware创建虚拟机&#xff0c;因为过程比较简单就没有截图了&#xff0c;根据下面步骤来就行。2.网络配置3.MobaXterm连接CentOS1.new session2.点击ssh&#xff0c;输入虚拟机的IP地址即可 4.进行阿里云换源1.进入2.下载wg…

AMD:抢占AI芯片宝座

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结&#xff1a; &#xff08;1&#xff09;AMD受益于AI芯片的出口限制&#xff0c;使其能够获得更多的中国市场份额&#xff0c;并增强其在AI芯片市场的地位。 &#xff08;2&#xff09;AMD的处理器&#xff0c;特别是E…

ctfshow-web入门命令执行29-36

29 源代码给了禁用flag 使用tac、nl ?cecho nl f*; ?cecho tac f*; 30 多禁用了system和php 和上题区别不大&#xff0c;使用上一题命令就能解 ?cecho nl f*; ?cecho tac f*; 31 禁用了空格使用%09代替 ?cecho%09tac%09f*; 32 禁用了echo 使用php伪协议 ?cinclud…

从零开始学习搭建量化平台笔记

从零开始学习搭建量化平台笔记 本笔记由纯新手小白开发学习记录&#xff0c;欢迎大佬请教指点留言&#xff0c;有空的话还可以认识一下&#xff0c;来上海请您喝咖啡~~ 2023/10/30&#xff1a;上份工作辞职并休息了几个月后&#xff0c;打算开始找个关于量化投资相关的工作。面…

云原生之使用Docker部署slash书签共享平台

云原生之使用Docker部署slash书签共享平台 一、slash介绍1.1 slash简介1.2 slash特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载slash镜像五、部署slash书签共享平台5…

2模块和包的一些总结:导入库和模块

感觉这块好零散呀&#xff0c;应该怎么去写呢&#xff1f;截图吧 1、导入多个模块的方法 #导入多个包有几种办法 # 1.用点号 # 2.用逗号import p1.Tool import p1.sub_p.sub_xxxprint(p1.Tool.num) print(p1.sub_p.sub_xxx.num)import p1.Tool,p1.sub_p.sub_xxx print(p1.Tool…

基于纵横交叉算法的无人机航迹规划-附代码

基于纵横交叉算法的无人机航迹规划 文章目录 基于纵横交叉算法的无人机航迹规划1.纵横交叉搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用纵横交叉算法来优化无人机航迹规划。 …

【2023.10.30练习】C语言-循环右移字符

计算机能力挑战初赛2020.19题 题目描述&#xff1a; 现要对一个由字符a-z和A-Z组成的字符串进行解密&#xff0c;已知加密规则是&#xff1a; 字符串中所有字符分别在大写或小写的字母表中被循环左移5位(fGh-->aBc)&#xff0c; 输入&#xff1a;一个加密过的字符串&#…

【MySQL索引与优化篇】数据库优化及性能分析工具使用

数据库优化及性能分析工具使用 文章目录 数据库优化及性能分析工具使用1. 数据库服务器优化的步骤2. 查询系统性能参数3. 定位执行满的SQL&#xff1a;慢查询日志4. 查看SQL执行成本&#xff1a;show profile5. 分析查询工具&#xff1a;explain5.1 id5.2 type 6. explain进一步…

【AI视野·今日Sound 声学论文速览 第三十一期】Mon, 23 Oct 2023

AI视野今日CS.Sound 声学论文速览 Mon, 23 Oct 2023 Totally 9 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Two-Stage Triplet Loss Training with Curriculum Augmentation for Audio-Visual Retrieval Authors Donghuo Zeng, Kazushi Ikeda跨模态…

dp三步问题

三步问题 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 class Solution { public:int waysToStep(int n) {vector<int> dp(n1,1);if(n1) return 1;dp[1]1;dp[2]2;for(int i3; i<n1; i){dp[i] ((dp[i-1]dp[i-2])%1000000007dp[i-3])%100…

类变量/方法、main语法、代码块

一.类变量和方法 思维导图概览&#xff1a; 1.1类变量&#xff08;静态变量&#xff09; 1.什么叫做类变量/方法&#xff1f; ——给类中的成员属性或成员方法加上static关键字进行修饰&#xff0c;类变量/方法也叫做静态变量/方法&#xff0c;静态变量/方法被类的自身所有对…

C/C++ 飞翔的小鸟

载入问题&#xff1a; 解决之后效果&#xff1a; 放在main函数里面进行封装&#xff1a; 效果展示: 实现下坠 放进while&#xff08;1&#xff09;里面不断进入循环&#xff0c;每次进入循环&#xff0c;鸟的y坐标值就会发生变化&#xff0c;以此实现下下坠效果 效果展示&#…