set和map介绍
set和map是C++ STL中的关联式容器,关联式容器是容器里面存储的是<key, value>结构的
键值对,在数据检索时比序列式容器效率更高
键值对:
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义
set和map底层的实现都是使用的平衡搜索二叉树(红黑树),所以不能随便修改key,否则会破坏红黑树的搜索规则
set的key是不允许重复的,在插入的时候,如果set中已经有了要插入的数据,则不会插入,所以set具有去重的功能,同样,map也是不允许key重复的
set的基本使用
set头文件 :#include
set的定义:
pair是一个构造key 和 value结构的对象,内部有两个成员first(key),second(value)
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
set的构造函数:
插入:insert
set是红黑树结构,所以无法插入重复的值
删除:erase
查找:find
如果set中有要查找的元素,返回这个元素的迭代器,如果没有,返回set最后一个元素的下一个位置的迭代器
清空:clear
清空set中所有的数据
判空:empty
set为空返回true,不为空返回false
元素个数:size
交换:swap
将两个set对象的数据交换:
迭代器:
迭代器的使用方法类似于指针,需要通过*解引用来访问数据,但是在范围for中不需要解引用
在创建结构体对象的时候,需要指明set类型:
迭代器关键字:iterator
定义格式:set<类型> iterator 迭代器名
正向迭代器:
begin(返回第一个元素迭代器)
end(返回最后一个元素的下一个位置)
迭代器的使用和指针类似,是可以前后++ – 的
【注意】end返回的不是最后一个元素,而是最后一个元素的下一个位置
反向迭代器:
反向迭代器和正向迭代器的返回值完全相反使用起来也是相反的操作
正常思维来说,rbegin返回的是最后一个元素的迭代器,如果想要向前访问数据,依次–操作即可,但是反向迭代器的设计异于常人,如果想要向前访问,使用的是++操作
rend返回的是第一个元素的上一个位置,如果想要向后访问,不是使用++,而是–操作
所以反向迭代器完全是和正向迭代器相反
反向迭代器的关键字是reverse_iterator
反向迭代器的定义:set<数据类型> reverse_iterator 迭代器名
rbegin(返回最后一个元素的迭代器)
rend(返回第一个元素的前一个位置)
set迭代器的注意事项:
在删除迭代器的值后,如果再次访问迭代器就会报错
map的基本使用
map的头文件:#include
map的构造:
插入:insert
删除:erase
查找:find
数据个数:size
清空:clear
交换:swap
以上三个接口和set的使用方法一样的,这里就不上代码了
迭代器:
map的迭代器和set的迭代器使用方法是一样的
正向迭代器:
beign(返回第一个元素的迭代器)
end(返回最后一个元素下一个位置的迭代器)
反向迭代器:
rbegin(返回最后一个元素下一个位置的迭代器)
rend(返回第一个元素的上一个位置的迭代器)
## 【重点】:[ ]的使用
在map中,可以通过[ ]来修改value的值,[ ]中填入key,即可找到value
这里再说一个有意思的操作,使用[ ]插入:
【说明】:使用[ ]插入,如果插入的key已经存在,则会修改value 的值,如果不存在,则将key和value插入
我们来做一个简单的题目:统计数组中水果出现的次数
这里是用[ ]来计算是不是特别的巧妙
multimap和multiset
其实multi系列的容器没什么好说的,看一下文档介绍吧
-
multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
-
在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成
的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器
中进行修改(因为元素总是const的),但可以从容器中插入或删除。 -
在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则
进行排序。 -
multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭
代器遍历时会得到一个有序序列。 -
multiset底层结构为二叉搜索树(红黑树)。
注意: -
multiset中再底层中存储的是<value, value>的键值对
-
mtltiset的插入接口中只需要插入即可
-
与set的区别是,multiset中的元素可以重复,set是中value是唯一的
-
使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
-
multiset中的元素不能修改
-
在multiset中找某个元素,时间复杂度为 O ( l o g 2 N ) O(log_2 N) O(log2N)
-
multiset的作用:可以对元素进行排序
-
Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,
value>,其中多个键值对之间的key是可以重复的。 -
在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内
容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,
value_type是组合key和value的键值对:
typedef pair<const Key, T> value_type; -
在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对
key进行排序的。 -
multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代
器直接遍历multimap中的元素可以得到关于key有序的序列。 -
multimap在底层用二叉搜索树(红黑树)来实现。
注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以
重复的。
multimap的使用
multimap中的接口可以参考map,功能都是类似的。
注意:
- multimap中的key是可以重复的。
- multimap中的元素默认将key按照小于来比较
- 使用时与map包含的头文件相同: