在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 l o g 2 N log_2 N log2N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个unordered系列的关联式容器。
unordered系列的关联式容器
unordered_map、unordered_set、unordered_multimap、unordered_multiset
接下来要讲无序的map和set,这是为了提高查找效率。
这4个无序的容器与有序的相比而言,其一,查找效率更高;其二,不支持反向迭代器,仅支持++,不支持–,其三,有序的底层用红黑树,STL 底层采用哈希表实现无序容器时,会将所有数据存储到一整块连续的内存空间中,并且当数据存储位置发生冲突时,解决方法选用的是“链地址法”(又称“开链法”)。
键值对的理解:记作键:值 (key:value)。key 是索引,value 是数据。key是唯一的。
无序容器 | 功能 |
---|---|
unordered_map | 存储键值对 <key, value> 类型的元素,其中各个键值对键key不允许重复,且该容器中存储的键值对是无序的 |
unordered_multimap | 和 unordered_map 唯一的区别在于,该容器允许存储多个键相同的键值对 |
unordered_set | 不再以键值对的形式存储数据,而是直接存储数据元素本身(当然也可以理解为,该容器存储的全部都是键key 和值 value 相等的键值对,正因为它们相等,因此只存储 value 即可)。另外,该容器存储的元素不能重复,且容器内部存储的元素也是无序的 |
unordered_multiset | 和 unordered_set 唯一的区别在于,该容器允许存储值相同的元素 |
unordered_set
数据无序,不允许数据冗余,提供了哈希负载因子调节函数,其余功能类似有序set
unordered_map
数据无序,允许数据冗余,提供了桶操作相关函数以及哈希负载因子调节函数,其余功能类似有序set。unordered_multimap不支持operator[]操作。
operator[key] 函数
返回与key对应的value,没有一个默认值。注意:该函数中实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,将key对应的value返回。
桶操作函数
函数声明 | 功能 |
---|---|
size_t bucket_count()const | 返回哈希桶中桶的总个数 |
size_t bucket_size(size_t n)const | 返回n号桶中有效元素的总个数 |
size_t bucket(const K& key) | 返回元素key所在的桶号 |
比较
对于无序数据的insert,unordered系列效率更高;对于有序数据的insert,order系列效率更高。==>插入的对比不太明显,两者在数据量不同(万、百万)、环境不同(windows、linux)时,效率不一样
对于无序数据的erase,unordered系列效率更高;对于有序数据的erase,order系列效率更高。==>删除的对比不太明显,两者在数据量不同(万、百万)、环境不同(windows、linux)时,效率不一样
对于数据的find,unordered系列效率更高。==>find的对比很明显,unordered系列的查找效率极高!
unorder系列的优势就是find功能。
与有序容器仅有一个区别,无序容器是不会对存储的键值对作排序。实际场景中如果涉及大量遍历容器的操作,建议首选关联式容器;反之,如果更多的操作是通过键获取对应的值,则应首选无序容器。