Map和Multimaps.docx
- 文档编号:6877363
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:20
- 大小:52.37KB
Map和Multimaps.docx
《Map和Multimaps.docx》由会员分享,可在线阅读,更多相关《Map和Multimaps.docx(20页珍藏版)》请在冰豆网上搜索。
Map和Multimaps
maps和multimap
1简介
map和multimap将key(键值,或理解为排序关键字)/value(值)作为元素,成对
存储,它们可根据key的排序准则自动将元素排序。
multimap允许重复键值,maps不允许。
如下图:
使用map和multimap需要使用头文件<map>,在使用这个头文件时,要用标准名称空间(usingnamespacestd;)。
map和multimap的元素是key/value对,map可以作为映射式数组使用,比如存储学生信息时,学生的学号和姓名就是一一对应的映射关系,或者在存储电话号码时,人名和电
话号码也是映射关系,等等。
map和multimap根据元素的key自动对元素进行排序。
根据已知的key搜寻某个元素
时,能够有很好的性能,根据已知的value搜寻元素时性能则很糟糕。
"自动排序”这一性质使得map和multimap有很重要的限制:
不能直接改变元素的
key,因为这会破坏正确顺序。
要修改元素的key,必须先移除拥有该key的元素,然后插
入拥有新的key值的元素。
2map和multimaps的构造函数
表1map和multimap的构造函数
操作
效果
mapc
产生一个空的map/multimap,其中不含任何
丿元糸
mapc(op)
以op为排序准则,产生一个空的
map/multimap
mapc1(c2)
产生某个map/multimap的副本,所有兀素均被复制
mapc(beg,end)
以区间[beg;end]内的兀素产生一个map/multimap
mapc(beg,end,op)
以op为排序准则,利用[beg;end]内的兀素生成一个map/multimap
在表1中的map可以是以下形式:
表2表1中map的可选形式
map
效果
map
一个map,以less<>(实际上就是小于号<”
为排序准则
map
一个map,以op为排序准则
multimapvkey,elem>
一个multimap,以less<>为排序准则
multimapvkey,elem,op>
一个multimap,以op为排序准则
表2中,key为键值类型,elem为value值的类型。
op可以是less<>或者是greater<>,在排序准则中要指定key的类型。
return0;
mapvfloat,string,greater
量a之间的关系。
实际上,map是一种容器,这种容器可以存储任何类型的变量,但是具体
你需要什么类型的map,还需要告诉编译器,比如在本例的map容器,以float类型为key,
以string类型为value。
这些是属于泛型编程的内容,具体细节以后接触C++的时候就会明
白。
要注意红色高亮部分的两个“>”中间要有一个空格,因为连续的两个“>”会被编译
器解释为移位操作符,导致语法错误。
以上程序片段在VC中编译会有一大票C4786警告,不必理会,在其他编译器中无此
问题。
3数据的插入和删除
3.1插入数据
1、使用pair<>和insert语句:
#include
#include
#inelude
intmain()
{
mapvfloat,string,greater
}
其中pair的功能是把pair后面尖括号里指定的两种类型合并为一个容器存储数据都是相关联的数据成对存储的,所以要先把两个值合成一个
如上面例子中,pairvfloat,string>(22.3,hello")实现的功能就是把一个
并成一个pair类型变量(实际上这就是面向对象中所谓的"对象”,对象与类的关系类似于
c语言中内置类型如int与该类型变量的关系。
实际上pair是一个类)。
这个pair类型变量的一对值分别是浮点值22.3和字符串"hello”。
(注意string也是一个类,和c语言中的c风格字符串不一样,要使用string的话需要包含头文件<cstring>)
注意以上代码中黄色高亮部分:
"hello"和"ok"实际上都是conststring,而第一条insert
语句中的pair指定的是string类型,这时pair会做一个自动的隐式类型转换,把conststring
类型(也就是"hello")变成string类型。
2、使用make_pair函数和insert,这是最方便的方法。
#include
#include
#include
usingnamespacestd;
intmain()
{
map
mymap.insert(pair
mymap.insert(pair
mymap.insert(make_pair(50.0,"happy"));
return0;
}
make_pair也会执行必要的隐式类型转换。
但是在VC6.0中编译时mymap.insert(make_pair(50.0,"happy"));这一句通不过,"happy"被认为是char[6]类型,没有被自动转换成string。
在devc++中编译顺利通过。
看来VC6.0这个开发环境存在的主要目的
是为基于MFC的win32编程服务的,用到C++核心内容时,会深刻感受到VC6.0的不标准。
3、使用value_type禾口insert
#inelude
#inelude
#inelude
usingnamespaeestd;
intmain()
{
mapvfloat,string,greater
mymap.insert(pair
mymap.insert(pair
mymap.insert(make_pair(50.0,"happy"));
mymap.insert(map
:
value_type(53.7,"lucky"));return0;
}
4将map视为关联式数组,以数组下标方式(即[])
非常量(Non-const)的map提供下标操作符以支持元素的直接存取。
如表3
操作
效果
m[key]
返回一个引用(C++中的一种新类型,是一个变量的别名,可以按照指针来理解,但是使用起来比指针简单,而且效率比指针高),
该引用指向键值为key的元素。
如果该元素尚未存在,则插入该元素。
注意m[key]中的索引值"key"不一定是整型,因为他是map容器每个元素的key,可以
是任意类型,这样可以方便地实现关联式数组。
#inelude
#inelude
#inelude
usingnamespaeestd;
intmain()
{
map
anothermap.insert(make_pair("zhangsan",1.75));
anothermap.insert(make_pair("lisi",1.72));
anothermap.insert(make_pair("zhaoliu",1.69));
anothermap["lisi"]=1.77;
anothermap["wangwu"]=1.66;
return0;
}
以上代码黄色高亮部分中,第一句
anothermap["lisi"]=1.77;
在anothermap中已经存在了key值为”isi"的元素,那么这一句将会用1.77覆盖掉原来
lisi所对应的值(1.72);
黄色高亮部分中,第二句
anothermap["wangwu"]=1.66;
another中不存在key值为"wangwu"的元素,那么会向anothermap中自动插入一个新元素,key值为"wangwu”并把这个新插入的元素的value设置为某个默认值(比如当value
的类型为int时,会默认设置为0),然后再把1.66赋给这个新插入元素的value。
前面说过,map中不能存在key值相同的元素。
因此,在使用insert添加map新元素时,如果新插入元素的key值与容器中原有元素的key值有重复,则insert会失败。
但使用下标
方式插入则不会出现插入失败,因为如果在原有元素中存在与新插入元素key值相同的元
素,则会用新插入元素的value去覆盖掉原有元素的value。
这是下标方式的优点,也是其
缺点,比如这会导致我们错误地覆盖掉容器中的原有元素,或是不小心错误插入新元素。
比
如:
cout< 在输入"zhangsan"时,少敲了一个"n",这将会导致向anothermap中插入一个新值,其key为"zhangsa",value为0。 另外,以下标方式向map中添加元素的速度要比insert方式慢许多。 4迭代器(iterator) 在STL中,迭代器的角色类似于C/C++中的指针。 其声明方式如下: mapvstring,float>: : iteratorpos; 其中mapvstring,float>表明这个迭代器的类型,mapvstring,float>: : iteratorpos表示声明一个迭代器pos,其类型为mapvstring,float>。 迭代器用法: #inelude #inelude #ineludevestring>usingnamespaeestd; intmain() { mapvstring,float,less anothermap.insert(make_pair("zhangsan",1.75)); anothermap.insert(make_pair("lisi",1.72)); anothermap.insert(make_pair("zhaoliu",1.69)); anothermap["lisi"]=1.77; anothermap["wangwu"]=1.66; mapvstring,float>: : iteratorpos; for(pos=anothermap.begin();pos! =anothermap.end();pos++){ return0; } 黄色高亮部分第一句声明了迭代器pos。 第二句在for循环中,首先用到了map容器的 begin()成员函数,该函数返回调用该函数的对象(也就是anothermap)的第一个元素的迭代器 (可以理解为指针);end()函数返回的迭代器指向了调用该函数的对象的最后一个元素后面的位置。 如下图: begin() 图中容器中共有7个元素a,b,c,d,e,f,begin()所返回的迭代器指向a,end()所返回的 迭代器指向最后元素g的后面的位置。 另外需要注意的是for循环中的循环终止条件不是pos =anothermap.end()。 j具体原因大家以后学到操作符重载的时候就会明白。 5对key和value值的访问 当迭代器pos指向map容器中某个元素,以下表达式pos->first 获得该元素的key以下表达式 pos->second 获得该元素的value intmain() map anothermap.insert(make_pair("zhangsan",1.75)); anothermap.insert(make_pair("lisi",1.72)); anothermap.insert(make_pair("zhaoliu",1.69)); anothermap["lisi"]=1.77; anothermap["wangwu"]=1.66; map : iteratorpos; for(pos=anothermap.begin();pos! =anothermap.end();pos++){ cout< } return0; } 其输出结果如下: lisi1-77uangruu1*66 zhaollu1.69 Processreturned0executiontime: 0.031s TressanyheyCocontinue. 不能通过pos->first这种方式改变元素的key: pos->first="xuqi”//编译时出错 记住最前面提到的: 不能直接改变元素的key,因为这会破坏正确顺序。 要修改元素的 key,必须先移除拥有该key的元素,然后插入拥有新的key值的元素。 如果元素本身value的值非const,可以通过pos->second来改变value的值,如下面的语句: pos->second=1.73;〃OK 6容器元素的删除 6.1通过erase()函数删除具有某个key值的单个元素 女口: 要删除容器中拥有某个key值的元素,可以通过以下方式: anothermap.erase("lisi"); 完整代码如下: #include #include #include usingnamespacestd; intmain() { mapvstring,float,less anothermap.insert(make_pair("zhangsan",1.75)); anothermap.insert(make_pair("lisi",1.72)); anothermap.insert(make_pair("zhaoliu",1.69)); anothermap["lisi"]=1.77; anothermap["wangwu"]=1.66; map : iteratorpos; for(pos=anothermap.begin();pos! =anothermap.end();pos++){ cout< } cout< anothermap.erase("lisi"); for(pos=anothermap.begin();pos! =anothermap.end();pos++){ cout< } return0; } 运行结果如下: lisi1.7? zhangsan1.75 zhaoliu uanguu1.6& zhdnywan1.75 zhaoliu1. ProcessreturnedG<0x0>executiontime: 0-0&2sPressanykei/tocontinue 可以看到,key为"lisi"的元素已经从anothermap对象中被删除。 6.2通过erase()函数删除某个位置上的元素 #include #include #inelude intmain() { mapvstring,float,less anothermap.insert(make_pair("zhangsan",1.75)); anothermap.insert(make_pair("lisi",1.72)); anothermap.insert(make_pair("zhaoliu",1.69)); anothermap["lisi"]=1.77; anothermap["wangwu"]=1.66; map : iteratorpos; for(pos=anothermap.begin();pos! =anothermap.end();pos++){ cout< } cout< pos=anothermap.find("lisi"); if(pos! =anothermap.end()) anothermap.erase(pos); for(pos=anothermap.begin();pos! =anothermap.end();pos++){ cout< } return0; } 运行结果: lisi1.77 1_66 zlianfifsan1.75 zliaoliu.1.69 uanguu1 chang&dn1.75 zhaoliui1.■石9 Processreturned0<0x0>executiontime: 0.015sPressNnykeytocontinue- 高亮部分的find()函数用来搜寻拥有某个key的第一个元素,并返回一个指向该元素的 迭代器。 如果没有找到这样的元素,就返回该容器的end()。 注意,不能用find()搜索拥有某 特定value的元素。 如果我们需要删除map中具有某个value值的元素,可以通过如下方式: #inelude #inelude #inelude usingnamespaeestd; intmain() { mapvstring,float,less anothermap.insert(make_pair("zhangsan",1.75)); anothermap.insert(make_pair("lisi",1.72)); anothermap.insert(make_pair("zhaoliu",1.69)); anothermap["lisi"]=1.77; anothermap["wangwu"]=1.66; map : iteratorpos; for(pos=anothermap.begin();pos! =anothermap.end();pos++) { eout< } eout< map : iteratortemp; for(pos=anothermap.begin();pos! =anothermap.end();pos++)if(pos->seeond==1.75) { temp=pos; anothermap.erase(temp); break; } for(pos=anothermap.begin();pos! =anothermap.end();pos++) { eout< } return0; } 运行结果: lisi1-77 uamgvfu1.66 2han1-75 zhaoliu1.69 lici1.7? HBiragvfui1.66 zhaoliu1.69 Processreturned0<0x0>execu.tiontine: 0.000sPress钗nyke卯tocontinue- 首先要知道的是,不能通过以下方式删除具有某value值的元素: for(pos=anothermap.begin();pos! =anothermap.end();pos++) if(pos->second==1.75) anothermap.erase(pos); 因为对pos所指元素实施erase()之后,会使pos不再成为一个有效的anothermap迭代器,从而pos成为一种未定义的状态。 因此,要删除具有某个value的元素,需要按照上面高亮 部分代码所做的: 声明另一个该类型的迭代器temp,用pos去遍历整个容器的所有元素, 当发现第一个具有value值的元素时,把pos值赋给temp,然后用temp去删除。 6.3使用erase(形除某个区间内所有元素 #include #include #include usingnamespacestd; intmain() { mapvstring,float,less
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Map Multimaps