387.字符串中的第一个唯一的字符
想到了用哈希表,但是不知道该怎么用。
序列式容器:STL中的部分容器,如:vector、list、deque等,因为其底层为线性序列的数据结构,里面存储的是元素本身
关联式容器:里面存储的是<key, value>结构的键值对(保存映射关系),在数据检索时比序列式容器效率更高。STL总共实现了两种不同结构的关联式式容器:树型结构与哈希结构。
关联式容器 | 容器结构 | 底层实现 |
---|---|---|
set、map、multiset、multimap | 树型结构 | 平衡搜索(红黑树) |
unordered_set、unordered_map、unordered_multiset、unordered_multimap | 哈希结构 | 哈希表,哈希桶 |
set是按照一定次序存储元素的容器,这种次序使用set的迭代器遍历set中的元素,可以得到有序序列
- 注:与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值。set中插入元素时,只需要插入value即可,不需要构造键值对,并且每个value必须是唯一的(可以使用set进行去重)
- 注:set中的元素不能在容器中修改(元素总是const,修改无法保证数据的次序),但是可以从容器中插入或删除它们。
- 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序注:默认按照小于来比较,中序遍历后为升序序列
- set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。set在底层是用二叉搜索树(红黑树)实现的
注:接近完全二叉树,查找的时间复杂度为logN
set的构造:
set的迭代器:
set的容量:
set的修改操作:
multiset容器与set容器实现和接口基本一致,
唯一区别就是,multiset允许键值冗余,即multiset容器当中存储的元素是可以重复的。
对于find来说multiset返回底层搜索树中序的第一个键值为key的元素的迭代器。
map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
- 键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair value_type。
- 在内部map中的元素总是按照键值key进行比较排序以及查找。
- map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
- map支持下标访问符,即在[]中放入key,就可以找到与key对应的value(这里是在insert上的一个封装)。
set和map基本差不多,但是set是k模型,而map是kv模型,这导致在部分地方又有些不一样。
map的构造:
map的迭代器:
C++ 中的auto、auto&、auto&&、const auto&
map的容量与元素访问(set只能通过迭代器访问):
在元素访问时,operator[]通过key找到与key对应的value然后返回其引用,当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value。
map中元素的修改:
multimap容器与map容器的底层实现以及成员函数的接口都是基本一致,区别是multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。
对于find来说multimap返回底层搜索树中序的第一个键值为key的元素的迭代器
由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数