1.关联式容器
在前面的阶段,我们已经接触过STL中的部分容器,如:vector,list ,queue ,forward_list(单链表)等,这些容器都统称为序列式容器,因为其底层为线性序列的数据结构,里面储存的是元素本身。下面我们需要来学习一下关联式容器。它与序列式容器有什么区别呢?
2.键值对
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。 就好比我们在进行英汉翻译的时候,我们去搜索引擎上面搜索一个中文,我们要使用英文翻译,这样它就会显示该单词的英文。所以这里的英文和中文是一一对应的关系,即通过该单词,在词典中就能查到该单词的意思。
3.树形结构的关联式容器
根据场景的不同,我们会选择不同的数据结构,STL总共实现了两种不同结构的管式容器:树形结构和哈希结构。树形结构的关联式容器有四种:map,set,multimap,multiset。这四种容器的公共特点是:使用平衡搜索树作为其底层的结构,容器中的元素是一个有序的序列。下面我们来介绍一下这些容器。
4.set
首先,我们来看一看set的介绍,当然我们在使用set前,需要包一下头文件<set> 。
翻译: 1. set是按照一定次序存储元素的容器。
2. 在set中,元素的value也标识它,并且每一个value是唯一的。(当然,如果你想插入不同的value,就需要用到后面的mutilset)。set容器中的元素是不能在容器中修改,但是可以插入和删除它们。
3.在内部,set中的元素总是按照其内部比较对象所指示的特定严格的排序准则进行排序。所以说,我们再传参的时候,就必须指定比较函数,对于内置类型,我们可以不用写,但是对于自定义类型,我们必须重载运算符(<,>)。
4.set 容器通过key访问单个元素的速度较慢,是O(N) 。而我们后面学到的unordered_set就非常快,是O(1)。
5. set的底层是用二叉搜索树实现的。
5. set的使用
我们在定义的时候,需要指定存储类型,和比较的函数。如果对于内置类型来说,可以不写比较函数,但是存储类型必须要写。
T:set中存放元素的类型,实际底层存储<value,value>键值对
compare: set中元素默认按照小于来比较。(升序)
Alloc: set中元素空间的管理方式,使用STL提供的空间配置器来管理(现在我们可以了解一下就行)
当然,我们亦可以使用拷贝构造,这些都是可以的,前面已经了解了,就不再细说,我们主要是讲一些接口。
迭代器
对于迭代器来说,set的迭代器支持以上几种,迭代器的使用我们前面也说了,就不再细说。
容量
容量的操作有: 1.empty(),判断容器是否认为空,空返回1,非空返回0。
2.size(),返回容器的大小。
3.max_size(),返回容器的最大储存数。
修改
1.insert(),对于insert,它将插入元素到容器里之后,容器仍然会是一个有序列。
2.erase(),删除指定元素,有就删除。
3.swap(),交换两个set的值。
4.clear(),清空所有的元素,但是容器的容量大小不变。
5.emplace(),现阶段我们理解为就是insert就行了。
6.map
文档简介
https://legacy.cplusplus.com/reference/map/map/?kw=map
map的使用
key:键值对中的key类型
T:键值对中的value的类型
compare: 比较器的类型,map中的元素是按照key来比较的,缺省的情况下默认用小于来比较,还是和set一样,对于内置类型不需要传递,对于自定义类型来说就需要自己重载运算符,并显式的调用该函数。
注意:需要包含<map> 的头文件。
map的构造
我们还是简单的写了一个初始化列表来初始化tmp。当然我们也可以构造一个空的map,至于键值对,我们可以使用任何类型来充当他们。
当然,拷贝构造,和赋值运算符也都支持。
迭代器
迭代器还是和set一样。
容量
容量和set也是类似。
修改
map和set不同的是,map多了一个 [] 运算符,它可以返回value 的引用,并且可以修改它,而key是不能修改的,set则没有这个接口。
可以看到 [] 的效果,可以返回键值对的value 的引用,并且可以修改它。
当然,这些接口和set也相差不大。
比较特别的还有这些接口。
find :我们可以查询一个键值对的key ,并返回它的迭代器。
count: 返回我们需要查询的key 的个数。
7.multimap
头文件和map 相同。
注意:multimap和map的唯一不同的是,map中的key是唯一的,而multimap中的key可以是重复的。比如在现实生活中,我们会有同名的人,但是他们的身份证号码是不同的,我们可以通过身份证号码不用来区别他们。
特别的,multimap中就没有重载 [] ,因为我们再调用同一个key的时候,编译器就不知道返回哪一个key 对应的 value 了。
8.底层结构
前面对map/set/ multimap/multiset 进行了简单的介绍,再他们的文档中发现,这几个容器都是使用二叉搜索树来实现的,但是二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者是接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成为O(N),因此map,set 等关联式容器我们底层结构都是堆二叉树进行了平衡处理,即采用平衡树来实现的。