我们前面接触过的string、vector、list这些都算序列式容器,它们都有一定的关联性,即使随便换位置也无伤大雅,因为是它们靠位置顺序来保存的。但是今天的MapSet就不是了,它们算关联式容器,两个位置之间有紧密的联系,如果随意交换一下,那它们的结构就被破坏了,因为它们是靠关键字来保存和访问的。
Set
它就是我们之前模拟的Key的使用场景,但是又分为两种,一种就是我们之前模拟实现的,另一种则是Multiset,它是允许重复数据的
这里的T就是我们的Key,而为了防止出现不支持比较的情况,它还给了我们一个仿函数的参数,当然正常我们是用不到的。因为它的底层是红黑树,所以它的效率是logn,迭代器走的是中序,所以它也是有序的。
同时我们可以发现它的迭代器是双向迭代器,所以之后需要注意它只支持++ -- 。
Set的特性之前提到过,因为结构原因不支持改,所以它的核心操作其实就三个,增删查。
增
这里就可以看出来,它并不是单纯的排序,还带个去重的效果,又因为它贴心的想到了你不喜欢它的排序,所以提供了一个仿函数给你。
它更贴心的为你准备了一次就初始化完。
删
除了上面的删法还能指定删
需要注意的是这里的返回值是删除的数据个数,所以即使删除的是0也没关系。
不过需要注意的是这里删除完,不论是替代的删还是直接删除节点,编译器都是认为失效的,因为它已经不是原本的它了。
查
查就很简单了,没那么多弯弯绕绕。不过有另一种比较特别的找法。
count本身是计数的,但是如果说这个数本身就不存在,那么就返回0。
以此来实现找的功能。
同时补充一点,Set为了实现迭代器区间的操作,给了两个成员
lower_bound和upper_bound
这两个就是取出一个区间,并且在这个区间内进行操作。
它们并不要求你给非常准确的区间,只要提供大概就好,lower取大于等于,up取大于。
Multiset
首先Multiset和set没有多大的区别,只是Multiset允许插入重复值,而Multiset遇到第一个要找的值时并不会直接返回,它是走中序,返回的是中序的第一个返回值。
而count在set有就是1没有就是0,到了Multisett就是返回个数和0了
而删除则是删除一个区间。
这样未免有点麻烦
这样多方便
Map
比之前的key之外多了一个key_value ,也就是说它按照key来排,但是多了一个记录可变值的key_value。除了这一点其他的其实都差不多。
那么多了一个key_value,它就支持改的操作了。
不过在此之前,我们需要先了解,它还多了一个pair的模板类型,它有两个参数也就是我们的key和key_value,它支持更改的也是key_value。
它的遍历也应为pair的结构有所变化
first就是key,是不能更改的,而second就是key_value,这个才是能改的。也因为编译器不能一下返回两个数据,所以它用pair包装了一下,让我们可以用->访问到数据。
以及更方便的初始化
到这Map其实就差不多了,除了pair这个结构上的区别,功能实现起来都差不多。
需要注意的点就是它的排序只受到first的影响,如果不是multimap版本,那么两个一样的first但是second不一样,它只会插入第一个,不会受到second的影响。
另一个需要注意的就是这里的operator[],这里的方括号是取得first,但是返回的是second。
而它厉害之处也在于这个pair结构。
这里的[]除了大伙能猜出来的查找修改,还带有插入功能,
不看别的,就这个insert就证明我所言非虚,至少带个插入效果。我们细细的扒一下insert.
不得了,人家的返回值也是个pair,不过这里的pair存的是迭代器和bool类型。
我们可以浅显的理解为iterator是一个迭代器,这个迭代器要么指向新插入的元素,要么就是已有元素的节点,而second的bool存的则是如果成功插入就是true否则就是false,所以咱们想知道到底插入成功没有是看第二个值,所以它在插入的过程中还兼顾到了查找的功能,而这个迭代器里存的是pair类型(不是这里的迭代器pair,而是前面提到过得那种string string类型的pair),所以我们可以通过迭代器的pair修改数据,又达成了改的操作。
不过因为它没有就插入有就返回位置的作用,我们除非特别确定某个值在里面,不然我们是不该使用它来找的,会存在相当一部分的风险。
我复制下来的,大伙将就着看,这里就是[]的实现,可以看到它用迭代器取到了pair,然后用bool记录是新插入还是已有的值,然后再通过iterator取到second返回,返回值是引用,所以它可以被修改,是不是一个很妙的结构。
这里可以看到咱们的cow牛变成了cow羊,并且咱还插入了两个新成员。所以结合以上的特性,这玩意咱还是要谨慎的使用它,因为它无论如何都会 “插入” 的效果确实杀敌一千自损八百。
Multimap
这玩意咱上面见识过了,就是允许重复的first嘛,但是map的插入咱也领教过了,加了这么个特性就是意味着一定能插入成功了,除非没内存了。
而它的删除也是一直删到first不一样位置,也就是类似于区间删。
二叉搜索树需要注意的就是这些,之后的AVL才是重头,这里仅仅只是需要了解它的底层和系统提供的版本的注意点而已。