容器 map 和 multimap
http://blog.csdn.net/lwbeyond/article/details/7313204#
1.底层结构不同:map——>红黑树,unordered_map——>哈希桶 2.使用场景:期望有序则用map,期望效率高则用unordered_map 3.效率:map低——>O(logN),unordered_map高——>O(1) 4.是否扩容:map不需要扩容,unordered_map需要进行扩容——>降低哈希冲突 5.空间利用率:map高,unordered_map低 6.插入方式:map:以红黑树方式插入 unordered_map:按照开散列方式插入 7.迭代器操作:map按红黑树中序遍历进行操作 双向++/-- unordered_map按逐个桶往后遍历 单向++ 8.是否关于key有序:map有序,unordered_map无序 9.map是C++98,unordered_mapC++11
C++11推出了4个新的关联式容器:unordered_map,unordered_set, unordered_multimap, unordered_multiset, 即加入了unordered系列的容器。 这4个关联式容器与map,multimap,set,multiset功能基本类似,最主要就是底层结构不同,使用场景不容。 如果需要得到一个有序序列,使用红黑树系列的关联式容器,如果需要更高的查询效率,使用以哈希表为底层的关联式容器。 unordered_map是c++11正式加入的对hashmap的官方实现。 unordered_map 原理 hashtable + bucket: unordered_map 内部采用 hashtable 的数据结构存储,每个特定的 key 会通过特定的哈希运算映射到一个特定的位置。 一般来说,hashtable 是可能存在冲突的,即不同的key值经过哈希运算之后得到相同的结果。解决方法是:在每个位置放一个桶,用于存放映射到此位置的元素, 当桶内数据量在8以内使用链表来实现桶,当数据量大于8 则自动转换为红黑树结构 也就是有序map的实现结构。 插入过程是: 1、得到 key; 2、通过 hash 函数得到 hash 值; 3、得到桶号(一般都为 hash 值对桶数求模); 4、存放 key 和 value 在桶内; 取值过程是: 1、得到 key 2、通过 hash 函数得到 hash 值 3、得到桶号(一般都为 hash 值对桶数求模) 4、比较桶的内部元素是否与 key 相等,若都不相等,则没有找到。 5、取出相等的记录的 value。 定位时间复杂度为O(1),同 数组 或者vector之类的连续内存存储结构。 查询一个key最差的时间复杂度是: 首先进行一次hash运算找到桶的位置,然后使用链表或者红黑树来继续查找(所有元素在同一个桶里,其他桶位全为空,这个桶位其实就是一个数组下面挂红黑树也就是挂了一个map的结构),所以时间复杂度是计算hash+O(1)+O(lgn)。 但是这几乎是不可能的。在一个设计正常的hash函数里结果应该是偏向平均的,至少设计方向是偏向平均的。这样时间复杂度就是计算hash+O(1)+O(lg(n/m)), m是桶数(通常设计为2的n次方)。根据时间复杂度的取值规则时间复杂度为O(lgn/m)。 无论是查找效率还是插入、删除效率unordered_map都优于map。所以在对数据不要求有序的情况下,尽量使unordered_map。除非你对数据要求有序才去使用map. 一个桶内的数据量在8以内使用链表来实现桶,当数据量大于8 后转换为红黑树结构的原因: 嗯,根本原因还是红黑树的查找时间复杂度为log n,而链表为n吧;至于为何选择8,查到论坛上有两种说法: 1) 黑树的查找时间的平均复杂度为log n,而链表为n/2,8是一个分割点; 2)泊松分布的角度,,我没有理解。 https://blog.csdn.net/it_qingfengzhuimeng/article/details/99735683 https://www.cnblogs.com/linghu-java/p/10598758.html Ref: https://www.jianshu.com/p/56bb01df8ac7 https://www.cnblogs.com/tp-16b/p/9156810.html https://blog.csdn.net/baihebeijixing/article/details/104349309/