一 .
在C++中类似vector封装数组,string封装字符,List封装了链表,map与set则封装了二叉树。其中set与map封装的二叉树则是采用的红黑树的底层结构的,这种结构与一般的二叉树的类型有所不同,这种结构的二叉树更加平衡高效检索的二叉树,对存入的数据进行了排序化的存储。
二
(1)为什么map与set的插入比其它的序列的容器的插入速度要高
这是由于采用二叉树的数据结构,对其中一个节点的插入或删除类似链表我们只需改变这个节点的位置信息即可,把新插入或删除的节点重新指向下一个节点的信息即可,并不用对其余的数据进行内存的移动。而string与vector这样的insert插入或删除由于
(2)对于set或者map使用迭代器时注意的事项:
首选呢我们要注意对于这些容器来说,使用的begin,find以及end函数返回的都是迭代器类型的数据类型。但是注意find函数呢如果没有查找到在容器中相对应的值则会返回与end()一样的值。
其次呢在使用迭代时我们要注意迭代器的类型对于每个容器来说都定义了相应的迭代器的类型,例如string::iterator s1=s.begin() 此时就是利用字符串的第一个字符给迭代器进行赋值操作,然后我们只要对迭代器在这个字符串中进行操作即可。 vector<int>::iterator s1=s.begin() 此时是利用向量的第一个对字符串进行赋值操作,
map<int,int>::iterator s1=s.begin()则是利用map中的第一个数据进行赋值操作,这就是容器相对应的迭代器类型,对于每个容器的迭代器类型拥有着一套迭代器规定好的操作。由于是指针的形式,在vector与string中迭代器有<,>的比较,这是因为他们是连续的地址而关联类容器中则不行
注意返回的迭代器的类型是类似指针的形式,但是呢这个指针则有着类型如上所说的迭代器类型的指针,所以当改变原有容器的结构时我们要注意我们要重新对迭代器赋值,不能使用原有的迭代器,不然有可能会导致野指针的情况。
(3)对于set与map这两个容器的类型
multiset,multimap,unordered_map,unordered_set,unordered_multimap等组合,首先解释一下对于map,set我们只有一个key值当我们有相同的key值时,我们则会用后边出现的key值覆盖前边出现的key值,find函数则是寻找key值,返回key值所在的迭代器。multiset,multimap则是说呢我们可以有着相同的key值我们不会覆盖,我们会存储后续的key值。其中呢unordered则是无序的意思,即这类的关联容器的代表了存储时是无序的存储,但是这种存储是哈希表映射的存储,对于一个输入我们有一个key值输出,即y=f(x)的形式,这样使得函数的查找的复杂度在一个时间即可,而红黑二叉树的那种查找效率则在N(logN)这是由于对于有序的排序我们查找的最快的速度是二分法那就是对数次查找。
三 set容器的性质
(1)associative
在这个容器中并不是通过元素的绝对位置进行访问,而是通过他们的key值进行间接的引用
(2)有序性
在这个容器中所有的元素都是严格的弱序的关系(即小于或等于),被插入的元素也是按照这个顺序排列。
(3)set
元素的值也是识别set的关键
(4)独一无二的key
在set中没有两个元素能够有着相同的key
(5)动态分配
对于一个set来说,由于内部有着allocat函数能够动态分配内存。
四set的函数
(1)set初始化
set a{1,2,3};
set a={1,2,3};这种初始化与上边的一样
set a(迭代器指针,迭代器指针)存储的是这两个指针之间的数据,这个指针指向的数据要和容器里的value值的类型要一样,它包含了[first,last)first数据不包含last数据。
(2)set迭代器函数
begin()返回第一个元素的迭代,即指向第一个地址的容器
end()返回最后一个元素后边一个位置的东西,为空的
rbegin()返回翻转迭代对于翻转开始
rend()
cbegin()
cend()
crbegin()
crend()
(3)容器的容量
size()返回容器中元素的数量
empty()测试容器中元素是否为空
max_size()容器最大能够存储多少个元素
(4)容器的修改
insert()插入一个元素
erase()删除一个元素 erase(迭代器,迭代器)删除迭代器范围内的元素
a.swap(b)交换容器中所有元素的值 a与b容器的值交换
clear()清楚容器中所有的元素
emplace()
(5)操作
find()发现某个元素 并返回这个元素的迭代
count()计算某个元素出现的次数