c++中的关联容器

2023-11-08

c++中的关联容器主要是map、set,已经multimap、multiset。

为了讲map,得先将pair类型:pair就是一个两个类型的组合,比如一个人的学号就可以是pair<int,string>,其中的int是学号,string是名字。

map就是一个容器,里面装的就是若干个pair。每个pair的第一个元素,称为键(注意键的类型必须支持小于(<)操作!),第二个元素,称为值。对于普通的map,每个键都对应一个值。这样的看起来,键类似于数组的下标,而值类似于数组的值。map类定义了3种类型,分别为key_type、mapped_type、以及vaule_type。他们分别表示了键的类型、值的类型,以及一个pair类型,pair的第一个元素是键,第二个元素是值。

首先讲讲如何给imap添加元素:有两种的方法,使用键(下标)或者使用insert

使用下标这种方法与vector等类型的容器相矛盾。如果是一个空的vector,则不能使用下标直接访问,必须pusn_back进元素才行,直接访问会报错。而对于map如果没有这个键(下标),则会自动的向map中添加这个键,值为0。下标操作的返回值,就是这个键关联的值。利用这个性质,我们可以很方便的完成统计的功能,举个例子:

[cpp]  view plain copy
  1. int main()  
  2. {  
  3.     string str;  
  4.     map<string,int> wordCount;  
  5.     while(cin>>str)  
  6.     {  
  7.         ++wordCount[str];  
  8.     }  
  9.       
  10.     map<string,int>::iterator it_map = wordCount.begin();  
  11.     cout<<"word"<<"\t\t"<<"count"<<endl;  
  12.     for(;it_map != wordCount.end();++it_map)  
  13.         cout<<it_map->first<<"\t\t"<<it_map->second<<endl;  
  14.     return 0;  
  15.   
  16. }  


 

使用时如果键不存在,则赋值为0,然后对其自增。即变成了1。

insert方法有多个重载函数,表明你插入的是一个pair,还是一对迭代器指明的若干个pair,还是插入一个pair到指定的位置,但通常使用的插入一个pair,这个函数最关键是它的返回值。这个返回值也是一个pair,pair的第一个元素是指向该map类型的迭代器,另一个是bool类型的变量,表明插入成功与否。可以用insert重写上面的程序:

 

[cpp]  view plain copy
  1. int main()  
  2. {  
  3.     string str;  
  4.     map<string,int> wordCount;  
  5.     while(cin>>str)  
  6.     {  
  7.         //对于每个单词,都尝试去插入它  
  8.         pair<map<string,int>::iterator,bool>ret = wordCount.insert(make_pair(str,1));  
  9.         //通过检测返回值来判断插入是否成功  
  10.         if(!ret.second)  
  11.             //插入失败表明map中有这个单词,只需要把对应键的值自增即可  
  12.             ++ret.first->second;  
  13.     }  
  14.       
  15.   
  16.     map<string,int>::iterator it_map = wordCount.begin();  
  17.     cout<<"word"<<"\t\t"<<"count"<<endl;  
  18.     for(;it_map != wordCount.end();++it_map)  
  19.         cout<<it_map->first<<"\t\t"<<it_map->second<<endl;  
  20.     return 0;  
  21.   
  22. }  


那么如何读取map的元素呢?虽然我们也可以使用键来读取,但是潜在的问题是如果该键不存在,就会自动创建,这个特点并不是我们所希望的。我们可以通过count或者find函数来查找某个键是否存在。这两个函数的区别在于count返回的是出现的次数(对于map只能为0或者1),而find则返回的是指向该键的迭代器(如果没有找到,返回超末端迭代器:.end())。这意味着如果你是为为了统计是否存在,使用count就可以了,如果你找到某个元素并且还想使用它,那么find会比较合适。

删除元素使用使用erase操作,这与顺序容器差别不大。但是要注意的是,关联容器的顺序是按照“键”排列的。

下面通过一个小程序来说明:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3. #include <string>  
  4. #include <vector>  
  5. using namespace std;  
  6.   
  7. int main()  
  8. {  
  9.     string str;  
  10.     map<string,int> wordCount;  
  11.     while(cin>>str)  
  12.     {  
  13.         //对于每个单词,都尝试去插入它  
  14.         pair<map<string,int>::iterator,bool>ret = wordCount.insert(make_pair(str,1));  
  15.         //通过检测返回值来判断插入是否成功  
  16.         if(!ret.second)  
  17.             //插入失败表明map中有这个单词,只需要把对应键的值自增即可  
  18.             ++ret.first->second;  
  19.     }  
  20.       
  21.   
  22.     map<string,int>::iterator it_map = wordCount.begin();  
  23.     cout<<"word"<<"\t\t"<<"count"<<endl;  
  24.     for(;it_map != wordCount.end();++it_map)  
  25.         cout<<it_map->first<<"\t\t"<<it_map->second<<endl;  
  26.   
  27.     //count方法:对于map,返回1或者0  
  28.     int cnt = 0;  
  29.     cnt = wordCount.count("bird");  
  30.     cout<<"cnt"<<cnt<<endl;  
  31.   
  32.     //find方法:返回的是指向键的迭代器  
  33.     int occurs = 0;  
  34.     map<string,int>::iterator it = wordCount.find("bird");  
  35.     if(it != wordCount.end())  
  36.         occurs = it->second;  
  37.     cout<<"occurs = "<<occurs<<endl;  
  38.   
  39.   
  40.     //删除元素  
  41.     int del;  
  42.     string s1 = "hate";  
  43.     //使用值删除  
  44.     del = wordCount.erase(s1);  
  45.     if(del)  
  46.         cout<<s1<<" has been removed! "<<endl;  
  47.     else  
  48.         cout<<"can't find the word! "<<endl;  
  49.   
  50.     //使用迭代器删除  
  51.     map<string,int>::iterator iter = wordCount.begin();  
  52.     wordCount.erase(iter);  
  53.   
  54.   
  55.     return 0;  
  56.   
  57. }  


 

说完了map,我们在看看set。set只有键,没有值,所以他的vaule_type不是pair类型,而是key_type类型。同样的,它也支持insert、find、count操作。map比较适合于储存键值对应的情况,而set适合于储存键,判断键在不在这个集合中,比如黑名单之类的。

前面两种关联容器的特点是,键与值的对应关系是唯一的。而multimap或者multiset则支持一对多的关系。而且对于相同的键,总是连续的存储。由于这种一对多关系,所以multimap和multiset支持一些map和set没有的操作。比如lower_bound、upper_bound以及equal_range.它们分别返回的是指向某个键的第一个元素,最后一个元素的下一个元素以及这连个元素组成的范围。看一个综合例子:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3. #include <string>  
  4.   
  5. using namespace std;  
  6.   
  7. int main()  
  8. {  
  9.     multimap<string,string> authors;  
  10.     string author,work,searchItem;  
  11.   
  12.     //建立作者及其作品的容器  
  13.     do  
  14.     {  
  15.         cout<<"enter authors name"<<endl;  
  16.         cin>>author;  
  17.         if(!cin)  
  18.             break;  
  19.         cout<<"enter authors works"<<endl;  
  20.         while(cin>>work)  
  21.             authors.insert(make_pair(author,work));  
  22.         cin.clear();  
  23.     }while(cin);  
  24.   
  25.     cin.clear();  
  26.     //删除元素  
  27.   
  28.     cout<<"who is the author that you want erase:"<<endl;  
  29.     cin>>searchItem;  
  30.     /* 
  31.     //使用erase删除:输出对应键的所有值 
  32.     multimap<string,string>::iterator iter = authors.find(searchItem); 
  33.     if(iter != authors.end()) 
  34.         authors.erase(searchItem); 
  35.     else 
  36.         cout<<"cannot find the author!"<<endl; 
  37.     */  
  38.   
  39.     //使用equal_range或得迭代器删除  
  40.     typedef multimap<string,string>::iterator itType;  
  41.     pair<itType,itType> pos = authors.equal_range(searchItem);  
  42.     if(pos.first != pos.second)  
  43.         authors.erase(pos.first,pos.second);  
  44.     else  
  45.         cout<<"can not find this author!"<<endl;  
  46.   
  47.   
  48.     //输出删除结果  
  49.     cout<<"author\t\twork:"<<endl;  
  50.     multimap<string,string>::iterator itbegin = authors.begin();  
  51.     for(;itbegin != authors.end();++itbegin)  
  52.         cout<<itbegin->first<<"\t\t"<<itbegin->second<<endl;  
  53.   
  54.     return 0;  
  55. }  

FROM:  http://blog.csdn.net/thefutureisour/article/details/7683656



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++中的关联容器 的相关文章

  • Materialize时间组件datepicker汉化

    首先说明我用的是1 0版本 由于版本差异导致js调用的方法不一致 请注意
  • ubuntu20.04修改时间localtime

    根据网络上目前的一些语句设置都无法正常实现 主要原因在于 网上的办法都是基于 System clock synchronized 参数的值是 yes 但是我的该参数一直都是no 且根据网上常规办法无法实现修改时区 因此 我经过查找资料找到了
  • 安装nodejs时提示Leaving directory

    在按照标准的编译命令 configure gt make gt make install 在make的时候发生错误 deps v8 src base platform mutex h 210 error expected before co
  • 在线PDF保护解除器,完全免费,没有文件数量限制 - PDF在线解锁器

    通常一般的PDF文件我们可以使用PDF阅读器程序打开 并可以打印内容 复制文本或转换为其他格式 但是 有时你可能发现某些PDF文件虽然可以像普通PDF一样被我们查看 但却无法打印它或选择复制文本内容 这些文件是被PDF创建者加了权限保护的P
  • 2.1 pytorch官方demo(Lenet)

    实现一个图像分类器 pytorch官方demo TRAINING A CLASSIFIER PytorchDemo LeNet 介绍 Convolutions 卷积 Subsampling 下采样 Full connection 全连接 L
  • avive零头撸矿

    Avive 是一个透明的 自下而上替代自上而下的多元网络 旨在克服当前生态系统的局限性 实现去中心化社会 aVive 一个基于 SBT 和市场的 deSoc 它使 dapps 能够与分散的位置 oracle 和 SBT 关系进行互操作 您的

随机推荐

  • vue history模式 nginx配置

    vue history模式 nginx配置 wap为history路径 location wap try files uri uri router index index html index htm location router rew
  • jupyter notebook选择conda环境

    参考 https stackoverflow com questions 37085665 in which conda environment is jupyter executing 需要安装 conda install ipykern
  • IDEA插件-----Squaretest(自动生成单元测试)

    菜单栏就多了一项Squaretest 首先我们打开一个类 这个类就是我们即将要作为实验的类 这个类有7个public方法 因为Squaretest生成的单元测试方法都是只能生成public的 当然这也是合理的嘛 毕竟private的肯定被p
  • 02.java实现冷饮批发管理系统-页面设计之【选择店铺页面】

    需求 用户设置完收货地址 系统判断该地址里对应的商铺列表 HTML 预览
  • 1.7 起步 - 获取帮助

    1 7 起步 获取帮助 版本说明 版本 作者 日期 备注 0 1 loon 2019 3 19 初稿 目录 文章目录 1 7 起步 获取帮助 版本说明 目录 获取帮助 获取帮助 若你使用 Git 时需要获取帮助 有三种方法可以找到 Git
  • Vue中@click事件无效?@click.native中.native的含义和使用

    记录 click绑定事件的一个坑 问题描述 今天开发的时候 给组件绑定了 click事件 但是事件却没有执行 代码如下
  • 【Clion】自定义内容的自动补全——动态模板使用教程

    Clion的动态模板 动态模板的作用 实现自动补全 添加动态模板 添加动态模板的步骤 第一步是找到动态模板在哪里添加 打开clion的设置setting 找到编辑器选项editor 选择实时模板live template 选择C C 栏目
  • TCP协议疑难杂症全景解析

    说明 1 本文以TCP的发展历程解析容易引起混淆 误会的方方面面 2 本文不会贴大量的源码 大多数是以文字形式描述 我相信文字看起来是要比代码更轻松的 3 针对对象 对TCP已经有了全面了解的人 因为本文不会解析TCP头里面的每一个字段或者
  • Qt 主窗口与子窗口之间传值

    1 主函数向子函数传值 主窗口定义信号 子窗口定义槽函数 在主窗口将信号与槽连接起来 mainwindow h include
  • VTK笔记-使用vtkUnstructuredGrid类构建非结构化数据

    非结构化数据 非结构化点 非结构化点是在空间中离散随意分布的点 没有拓扑结构 几何机构也是完全没有规则的 非结构化点由顶点和多点的单元组成 非结构化点是一种简单但很重要的数据集类型 在部分可视化工作中会使用它来表示无结构的数据 非结构化网格
  • Windows Server 2019,开启多用户远程

    Windows Server 2019 开启多用户远程 最后记得重启计算机
  • DevopsCamp 第 2 期作业: 《cobra - 05 Cobra 的子命令》 简单说下 cobra 命令树和 gin 路由树的实现差异

    DevopsCamp 第 2 期作业 cobra 05 Cobra 的子命令 简单说下 cobra 命令树和 gin 路由树的实现差异 原文链接 https typonotes com posts 2023 02 14 devopscamp
  • PCL 体素滤波(C++详细过程版)

    体素滤波 一 概述 二 代码实现 三 结果展示 1 原始点云 2 滤波结果 一 概述 体素滤波PCL中经典的点云下采样算法 具体算法原理和实现代码见 PCL体素滤波器 为充分了解算法实现的每一个细节和有待改进的地方 使用C 代码对算法实现过
  • 力扣题---二叉树---相同的树

    题目连接 相同的树 首先我看题目要求以及例题 给你两棵二叉树的根节点 p 和 q 编写一个函数来检验这两棵树是否相同 如果两个树在结构上相同 并且节点具有相同的值 则认为它们是相同的 示例 1 输入 p 1 2 3 q 1 2 3 输出 t
  • FeignClient接口的几种方式总结

    FeignClient这个注解 已经封装了远程调用协议 在springboot的开发 或者微服务的开发过程中 我们需要跨服务调用 或者调用外部的接口 我们都可以使用FeignClient 一 FeignClient介绍 FeignClien
  • ChatGLM2-6B本地部署

    ChatGLM2 6B本地部署 ChatGLM2 6B 是开源中英双语对话模型 ChatGLM 6B 的第二代版本 在保留了初代模型对话流畅 部署门槛较低等众多优秀特性的基础之上 ChatGLM2 6B 引入了如下新特性 更强大的性能 基于
  • uniapp截取部分区域

    通过canvas来绘制截取部分 然后保存 html部分
  • 手把手教你,Selenium 遇见伪元素该如何处理?

    问题发生 在很多前端页面中 大家会见到很多 before after 元素 比如 百度流量研究院 比如 百度疫情大数据平台 以 百度疫情大数据平台 为例 累计确诊 文本并没有显示在 HTML 源代码中 如果通过常规的 xpath 元素定位方
  • Java 经典面试题:聊一聊 JUC 下的 LinkedBlockingQueue

    本文聊一下 JUC 下的 LinkedBlockingQueue 队列 先说说 LinkedBlockingQueue 队列的特点 然后再从源码的角度聊一聊 LinkedBlockingQueue 的主要实现 LinkedBlockingQ
  • c++中的关联容器

    c 中的关联容器主要是map set 已经multimap multiset 为了讲map 得先将pair类型 pair就是一个两个类型的组合 比如一个人的学号就可以是pair