一、前言介绍
map与set为C++STL容器中的关联式容器,与vector,list等序列型容器不同,关联式容器其存储的为<key,value>架构的键值对,在数据检索时比序列型容器更高效。还有一点,C++进行设计时,设计出两种关联式容器,一种为树形结构的关联式容器(map,set,multimap,multiset),另一种为哈希结构的关联式容器(unordered_map,unordered_set)其存储的都为键值对,只是内部底层结构不同。下面就正式开始我们的学习!
二、map容器介绍
使用前第一点,别忘记包含头文件<map>
map为关联容器,他可以按照一定的顺序(根据key值比较)进行存储键值对(<key,value)元素,键值key的作用为控制存储元素时的顺序和标识元素的唯一标志。value可以存储为与key相关的内容信息。键值key与值value两者的类型可以不相同,主要就看使用者想如何存储。在map的内部,key和value是通过value_type(pair)进行绑定在一起的。其底层结构为红黑树(高度平衡的二叉搜索树)。
Compare为其比较函数,如若未显示声明,则采用默认的比较函数(小于)进行比较。
map与unordered_map的不同之处在于,map访问元素的速度较慢,但map支持排序,也就是说元素插入到map中,其已经按照键值key排完序了。下面进行介绍map内部的常用函数和方法。
2.1构造函数
map支持构造一个空的map,也支持利用其它的map对象进行构造。如下图:
m1为定义一个空的map对象,m2为利用m1初始化m2,m3为利用迭代器进行初始化。另外,map还可对其内部比较顺序进行自定义(注意是根据键值key进行比较),如下图:
一般在对其比较顺序进行重定义时,最常用的方式为采用构造类重载()运算符的方式进行,当然也有其它方式,这里就不过多赘述。至此,构造函数大体完成。
2.2容量大小函数
map关于容量的函数,主要包括三个,可见下图:
empty():为判空函数,字面意思就是判断map是否为空,一个元素都没有才算为空,只要有元素,就不为空。
size():为求元素个数函数,可以直接求得map中的元素个数。
max_size():为返回map中可以容纳的最大元素数,一般不常用,了解即可。
调用方式与C语言结构体相类似,对象可以对象名.函数名,迭代器可以迭代器->函数名。使用较为简单,就不过多演示。
2.3元素访问[ ]和迭代器
map支持[ ]操作符,因此,其插入操作就变得十分简单了。其一般格式为 map变量名[key] = value。意思是将value赋值为键值为key的值。
但要注意的是,当key不存在时,此时访问出的value为0。
map的迭代器和其它容器的迭代器较为不同,如果想要利用迭代器访问键值key和值value,其一般格式为下图:
OK,了解到这两个操作后,我们就可以完成两个十分常用的操作了,分别是统计相同元素出现的次数和元素去重操作,其对于操作二利用下文讲到的set容器更好。
2.3.1统计相同元素
解决此题时,我们只需要对其进行插入map之后即可。
其中,最主要的操作就是 m[v[i]]++,其就利用[ ]操作符的插入功能。
2.3.2元素去重
对于其去重操作,我们就只需要在插入到map容器时,加上一个判断即可。
只需要判断,该元素在不在map中,在就不进入,不在就进入。
2.4修改函数
map的修改包括增删查改四种操作,下面依次来进行说明。
增:insert(key,value)函数,其调用格式一般为:map变量名.insert(key,value)。但此函数用的较少,因为有[ ]操作符,所以插入进map基本上使用[ ]操作符。
删:erase(key)函数,其调用格式一般为:map变量名.erase(key)。如果键值key不存在,也不会报错,只是什么都不做。
查:对于查找函数,map提供了find()函数和count()函数。
find( key )函数可以用来查找键值为key的值,找到了则返回其在键值key位置上的迭代器,找不到则返回end()位置的迭代器。
count( key )函数可以用来查找键值为key的值,与find不同的时,count函数找到了键值为key的值时,直接返回其对应的value,找不到则返回0。这一点与其[ ]操作符十分相似,因此可以认为count函数为其[ ]操作符的说明版。
在实际操作中,[ ]操作符也可以进行查找,因此,还是 [ ]操作符使用较为多些。
改:map并未提供直接修改函数,但我们可以通过 [ ] 操作符进行修改某一个键值key所对应的value。
对于上述函数讲解,本文只是进行说明了其常用的函数方式,每个函数其还有其它的使用方式,但并不很常用,因此,本文并没赘述。至此,map容器讲解大致结束,下面进行set容器。
三、set容器介绍
set容器其是没有键值key所对应的value值的,而且set容器内存储的值是不可重复的,并且元素的排列也是进行排序处理的。因此,set可以说是元素去重最有力的手段。废话少说,我们直接进入set的相关介绍。set的构造函数与map相等,这里就不过多赘述了。
3.1迭代器
set容器的迭代器与vector,string等容器大致相同,也就是可以把迭代器当作指针进行理解。其最多使用的也是begin()和end(),分别获取起始位置迭代器和最后一个位置的下一个位置迭代器,其一般使用格式为下图:
3.2容量大小函数
set容器关于容量大小函数与map几乎一样,也不过大赘述,调用方式也几乎相同。
3.3修改函数
写在修改函数前的一句话,set是不支持 [ ] 操作符的,一定注意。
增:insert(key / 迭代器,key)函数,set对于其插入有两种方式,一种是直接插入键值key,其格式为:set对象名.insert(key),这也是最常用的一种方式。另一种是在某个位置的迭代器位置上插入键值key,其一般格式为:set对象名.insert(某个位置迭代器,key)。
删:erase(迭代器 / key / 迭代器区间),set其删除有三种形式,可以进行单个元素删除,也可进行一段迭代器区间删除,其调用的一般格式为:set对象名.erase(某个位置迭代器 / 某个键值key / 某个迭代器区间)。
清空:clear()函数,清空clear()函数十分容易,其不需要传任何参数,直接调用即可,一般格式为:set对象名.clear()。
查找:find(key)函数和count(key)函数,先来看find(key)函数,find函数可以查找键值为key的值,找到了就返回其key位置的迭代器,找不到则返回end()位置的迭代器。count函数也可以查找键值为key的值,跟find函数不同的时,count函数查找成功后返回其非0的数,也就时true,找不到则返回0,也就是false。两者的调用也大致相同。格式为,set对象名.find(key),set对象名.count(key)。
改:set容器的修改并没有意义,因为她最主要的作用是存储元素,你想要存储另一个元素,直接插入即可,想要去除某个元素,直接删除即可,并不需要修改操作,因此,可以将插入和删除理解为修改操作。
至此,set容器的讲解也已告一段落,我们下次继续!!!