unordered_map,unordered_set等相关内容总结:
unordered_map和unordered_set是在开发过程中常见的stl数据结构。其本质是hashtable。在SGI_STL中,hashtable解决冲突的办法是拉链法。下面是一些对STL中堆hashtable中有关代码阅读的一些记录。
与之相关联的几个文件
第一部分:基本数据组织说明
hashtable的重要数据组织成员及辅助理解图(一个可能的hash数据结构情况)
_Bucket[] _M_buckets
_Hash_node_base _M_before_begin
size_type _M_bucket_count // 初始桶编号为1
size_type _M_element_count
由上图可以大致总结出在SGI-STL中hashtable数据的组织。几个要点:
①.hashtable实际上是维护了一个单链标。其头节点是一个特殊的成员_M_before_begin,其没有实际的数据。按照名字来理解,是第一个数据的前一个节点。
看一下对应的相关注释:
The non-empty buckets contain the node before the first node,this design makes it possible to implement somethiing like a std::forward_list::insert_after on a container insertion and std::forward_list::erase_afer on container erase calls._M_before_begin is equivalent to std::forward_list_list::before_begin.Note that one of the non-empty buckets contains &_M_before_begin which is not a dereferenceable node so the node pointer ina bucket shall never be dereferenced ,only its next node can be.
②._M_buckets这个二级指针的作用是什么,其目的是为了通用的可以使用_M_next()函数调用拿到每个桶的头节点(对于上图就是A,D)。比如_M_buckets[1]._M_next就是桶号为1的头结点A。_M_buckets[2]._M_next就是桶号为2的数据结构的头结点D。同时对于上图示例,应当有_M_before_begin和_M_buckets[1]是相等的(见黑色实线)
第二部分:几个常见接口的调用流程及调用栈
hashtable的定义
一些方便查阅的 using和typedef
①.插入的key是如何生成的
1.对于简单类型(int等):key计算的相关代码 const key_type& __k = this->_M_extract()(__node->_M_v())
计算key值是通过_M_extrace()来计算的,其是模板参数中的_ExtraceKey,
对于unordered_map在其定义中其模板参数中_ExtraceKey是__detail::Select1st 当定义为unordered_map<int,node>,insert(std::make_pair(0,node(a)); 其就返回pair中的first,即0。
struct pairhash {public:
template <typename T, typename U>
std::size_t operator()(const std::pair<T, U> &x) const
{
return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
}};
class abc {
std::unordered_map<std::pair<int,int>, int, pairhash> rules;
};
在这种情况下。__detail::Select1st获取到的数据就是std::pair<int,int>作为key对应的值
②.hash值如何生成
__hash_code __code = this->_M_hash_code(__key); ======> return _M_h1()(__k); ======> 在key为int的时候传递的参数是std::hash<int>
其最后会调用一个宏_Cxx_hashtable_define_trivial_hash(int),其在文件functional_hash.h中,该文件内涵多种不同类型的特化hash类。该文件定义了这些简单类型是如何hash的,下面是该宏的定义,看到这种情况下,其hash值就是直接强转成size_t类型。
③.如何确定一对pair的hash桶编号 size_type __bkt = _M_bucket_index(__k,__code) ====> return ___hash_code_base::_M_bucket_index(__k,__c,_M_bucket_count); } ====> return _M_h2()(__c,__n);
其中_M_h2获取的是模板参数_H2,对于unordered_map传递进来的是__detail::_Mod_range_hashing,其内容很简单。
可见桶编号值为hash值mod桶数量
④.rehash流程:主要思路是根据当前桶的数量和元素数量,在一个大的素数表中lowerbound查找下一步合适的桶编号。
下面是一个判定是否需要rehash桶以及如果需要后算出下一个合理的桶数量。至于最终的真正_M_rehash_aux流程。主题是数据指针迁移,并且保证新的new_buckets结构像前图一样。

- EventBus源码解析 源码阅读记录
EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...
- Elasticsearch6.3.2启动过程源码阅读记录
Elasticsearch6.3.2启动过程源码阅读记录 网上有很多关于es的源码分析,觉得自己技术深度还不够,所以这些文章只是看源码过程中的一个笔记,谈不上分析. 整个启动过程以类名.方法名,按顺序 ...
- x264阅读记录-2
x264阅读记录-2 7. x264_encoder_encode函数-1 查看该函数代码(Encoder.c文件)可以发现,该函数中注释很详细,对编码的整个步骤展示的也相对比较清晰. 在查看具体的代 ...
- x264阅读记录-1
x264阅读记录-1 采用x264版本是x264-snapshot-20060316-2245. 1. main函数 x264的main函数位于x264.c中,下面是main函数调用情况: (1)_s ...
- 《Javascript高级程序设计》阅读记录(七):第七章
<Javascript高级程序设计>中,2-7章中已经涵盖了大部分精华内容,所以摘录到博客中,方便随时回忆.本系列基本完成,之后的章节,可能看情况进行摘录. 这个系列以往文字地址: < ...
- 《Javascript高级程序设计》阅读记录(六):第六章 下
这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...
- 《Javascript高级程序设计》阅读记录(五):第六章 上
这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...
- 《Javascript高级程序设计》阅读记录(三):第五章 上
这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 这个系列,我会把阅读< ...
- 《Javascript高级程序设计》阅读记录(一):第二、三章
<Javascript高级程序设计>阅读记录(一) 这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较深入,而且实际使用价值较大的内容记录下来,并且注释 ...
随机推荐
- Vue父组件与子组件传递事件/调用事件
1.Vue父组件向子组件传递事件/调用事件 <div id="app"> <hello list="list" ref="child ...
- 在MVC中,网页head中页面主菜单间切换时,给当前菜单项添加样式
在Head部,添加如下代码: html代码 <ul class="nav navbar-nav" id="topmenu"> <li>& ...
- 【poj2409】Let it Bead Polya定理
题目描述 用 $c$ 种颜色去染 $r$ 个点的环,如果两个环在旋转或翻转后是相同的,则称这两个环是同构的.求不同构的环的个数. $r·c\le 32$ . 题解 Polya定理 Burnside引理 ...
- Java导出数据行写入到Excel表格:基于Apache POI
Java导出数据行写入到Excel表格:基于Apache POI import java.io.File; import java.io.FileOutputStream; import org.ap ...
- redis的sort排序
Redis排序命令是sort,完整的命令格式如下:SORT key [BY pattern] [LIMIT start count] [GET pattern] [ASC|DESC] [ALPHA] ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- 用centos 6.5 webservice 安装系统后的问题
编译pcre时:缺少一下库: yum -y install gcc yum -y install gcc-c++
- MDK5.13新建工程步骤
http://www.stmcu.org/module/forum/thread-600249-1-1.html 本人也是接触stm32没多久,之前用的MDK是5.1,现在用的是5.13,MDK5.0 ...
- struts2 文件下载的处理
- webstorm下搭建编译less环境 以及设置压缩css
webstorm自带less,不过要编译的话需要nodejs环境. 首先去node的主页下载对应版本的nodejs然后安装,下载地址:http://nodejs.org/ 安装完之后打开命令提示符(w ...