map multimap认识及使用
map就是上上篇二叉搜索树文中最后提到的key-value问题 和set一样是关联性容器底层是红黑树 就是在set基础上又加了一个模版类型的成员变量
后两个参数和set一样 前两个参数就是里面存的两个类型 第一个参数Key类型的成员变量用于插入查找删除比较 另一个参数类型的变量像是key的映射关系一样 不参与比较
如下图 之前二叉搜索树那里我们命名方式和这里有差别 容易搞混
insert第一个使用就是可以支持插入一个value_type类型的 value_type是什么呢
需要先说一下pair类型 它其实就是一个模版类 value-type其实就是当pair模版第一二个参数分别为map模版第一二个参数时候对其的重命名 所以此时pair里面的T1就是map的第一个参数Key T2就是map的第二个参数T 此时map里面Key类型的成员变量就是pair里面的first map里面T类型的成员变量就是pair里面的second
(上一篇二叉搜索树中我们是让第一个模版名为K第二个模版名为V 第一个成员变量是key 第二个成员变量是value)这块的起名规则有点容易弄乱
关于insert插入pair类型有以下四种方式
1. 创建pair对象初始化后进行插入2.匿名对象的方式3.用make_pair的方式(在c++11之前常用的 会返回pair类型)4.多参数隐式类型转换
在c++11后有了多参数隐式类型转换后当然使用第四种方式 第四种需要数据在{}里面才能
插入的时候如果插入重复的数据会插入失败 里面的key成员变量不能改变 value成员变量可以改变
上面的first就是pair里面的第一个成员变量也就是map里面的key second是pair里面的第二个成员变量也就是map里面的value key不可以进行更改 value可以修改是因为增删查的操作都是根据key来进行的
如果插入对象的key在map里面已经有的但是第二个参数value不同 不会进行更新数据 因为判断的时候是通过第一个参数key来判断的 如下图 里面已经有了一个对象key为跑value为run 此时再插入一个key为跑value为44的对象 这样不会更新数据 因为是根据key跑来判断的
下面的find count erase和set基本一样
find和set一样传对象的value然后如果找到了返回那个位置的迭代器 没有找到返回end()
count也和set一样找到key的话返回1没找到返回0 不用bool也是为了和multimap保持一致
也是支持迭代器及范围for方式打印的 不过打印不能像之前那样用下面这样的方式打印了 因为解引用之后是pair类型
要打印可以用解引用后再. 的方式或者-> (这里的->和之前list实现那里的方式一样 ->是重载过的 使用的时候其实还隐藏了一个->)
如下 我们可以通过map来统计各种水果出现的次数
但是其实范围for里面的内容只需要一行就可以完成了 如下用到了[]一行就完成了
为什么可以这样呢 我们来学习一下[]
map是支持[]重载的 之前的string和vector他们物理结构是连续的所以重载的[]很简单 但是map物理空间不是连续 它的[]需要一些设计
map的[]使用是在[]里面传key然后返回对应的value
map不仅可以通过[]来查找所传key位置然后返回value进行修改 而且还可以进行插入的操作
当查找的key在map里面已经有的话会返回已有key对应的value然后可以进行改的操作 如果里面没有这个key的话就进行插入一个key-value的对象 然后返回这个新插入的对象的value可以进行改的操作
那么为什么可以这样的 []重载是怎么实现的
[]重载里面其实就是调用了insert insert实现了插入查找(里面没有key)或者是查找的功能(里面有了key) 然后insert的返回值也是一个pair类型 不过这里的pair第一个参数是迭代器类型第二个参数是bool类型 总之迭代器就是key位置的迭代器bool类型的值插入成功就是true失败就是false 然后最后返回了key对应的value 文档里面名字有好多重命名的 看着有些乱 就是下面这样的关系
另外insert这样的返回值对于set也是一样的 也是pair<iterator,bool> 插入成功返回对象第一个参数就是新插入位置的迭代器第二个参数为true 插入失败返回的对象第一个参数就是已有插入数据位置的迭代器第二个参数为false
在把[]的重载理解了之后 我们就可以用[]实现插入查找和修改的操作如下
也可以理解刚刚下面这样为什么[]一行能替代那么多内容
如果str也就是传的水果在map里面没有的话就会插入这个水果第二个参数调用内置类型的构造初始化为0 然后最终会返回对应的value然后++ 如果map里面这个水果已经有了最终会返回对应位置的value然后++ 所以不管里面这个数据有没有都可以正确按照我们需求实现
multimap
multimap和map基本都相似 就是可以支持key相同对象的插入了 那么相应的find erase count等操作都有些差异了 multimap不支持[]的重载 因为里面可以有多个key相同的对象 而之前的map就是根据key来查找的 那这里key可以找到多个该返回哪个位置的value就不知道了 find和multiset一样会返回中序遍历的第一个