C++ unordered_map 实现原理

C++ 常用的map类容器就是 map 和 unordered_map

map的实现原理就是红黑树 每个节点到叶子节点最大树高不超过1 是平衡二叉树。查找的时间复杂度是O(lgn),但是插入和删除要维持红黑树的自平衡,所以效率较低。但是有序。

unordered_map是c++11正式加入的对hashmap的官方实现(之前标准c++没有对hashmap的官方实现,我们用的都是非官方的实现,例如平台自己的实现,hash_map中也建议以后都使用unordered_map不要使用hashmap),从名字可以看出这个结构是无序的,底层使用hashtable+buket的实现原理,hashtable可以看作是一个数组 或者vector之类的连续内存存储结构(可以通过下标来快速定位时间复杂度为O(1))处理hash冲突的方法就是在相同hash值的元素位置下面挂buket(桶),当数据量在8以内使用链表来实现桶,当数据量大于8 则自动转换为红黑树结构 也就是有序map的实现结构。

所以查询一个树最差的时间复杂度是:首先进行一次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。

另外unordered_map底层设计使用的是hashtable。hashtable槽数是根据需要分配的,但是一般都是2的n次方大小(unordered_map底层实现既是如此)。这种设计在计算桶号的时候有一个优势就是可以使用按位与(&)来加快计算。

int Index = hash & (length-1)

原理是在计算除法的时候如果被除数是2的n次方,其实就是把除数的二进制右移n位后被移掉的二进制对应的数值。

具体来说一下:

例如 9 % 8 

这里8 = 2的3次方,所以相当与把9的二进制(1001)右移3位,移掉的是001,那么余数(移掉的就是多余的数)就是1。

这里就是 9 & (8-1) 之所以是length-1这里是8-1是因为对2的n次方的二进制正好是1后面n个0。例如8的二进制是1后面3个0,1000。减1后正好是0111,后面的三个1按位与运算后正好完整的保留了除数被移掉的部分所以按位与的结果就是取余的结果。

所以这里可以加快运算,也算是一个小技巧。

 

  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
unordered_map的底层使用哈希表(hash table)来实现。哈希表是一种高效的数据结构,它可以在常数时间内进行插入、查找和删除操作。unordered_map使用哈希函数将键(key)映射到哈希值,然后将哈希值映射到存储桶(bucket)。每个存储桶中可以存储一个或多个键值对,具体的实现方式可以通过链表、红黑树等数据结构来解决哈希冲突。 当插入或查找一个键值对时,unordered_map会使用哈希函数计算键的哈希值,并找到对应的存储桶。如果存储桶为空,则直接插入键值对;如果存储桶不为空,则根据键值对的键与存储桶中已有的键进行比较,如果存在相同的键,则进行更新操作;如果不存在相同的键,则将键值对插入到存储桶中。 在unordered_map中,存储桶的数量通常是根据当前容量和负载因子(load factor)来确定的。负载因子是指哈希表中键值对的数量除以存储桶的数量。当负载因子超过一定阈值时,unordered_map会自动调整存储桶的数量,以保持哈希表的性能。 总之,unordered_map底层使用哈希表来实现,通过哈希函数将键映射到存储桶中,并使用链表、红黑树等数据结构来解决哈希冲突。这种实现方式使得unordered_map能够在常数时间内进行插入、查找和删除操作,具有高效的性能特点。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [unordered_map、unordered_set底层哈希表的实现机理](https://blog.csdn.net/qq_35987777/article/details/106668695)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C++——unordered_map浅析](https://blog.csdn.net/ly0724ok/article/details/117362251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值