unordered_map,unordered_set等相关内容总结:
unordered_map和unordered_set是在开发过程中常见的stl数据结构。其本质是hashtable。在SGI_STL中,hashtable解决冲突的办法是拉链法。下面是一些对STL中堆hashtable中有关代码阅读的一些记录。
与之相关联的几个文件 
gcc/libstdc++-v3/include/bits/hashtable_policy.h
gcc/libstdc++-v3/include/bits/functional_hash.h
gcc/libstdc++-v3/src/c++11/hashtable_c++0x.cc
 
 
 
第一部分:基本数据组织说明
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。
   对于如果定义类似于key不是简单类型的。需要自己定义hash函数否则不能通过编译,举例https://www.zhihu.com/question/30921173
    
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结构像前图一样。
 
 
 
 
 
 

 
 
 
 
 
 
 

STL hashtable阅读记录的更多相关文章

  1. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  2. Elasticsearch6.3.2启动过程源码阅读记录

    Elasticsearch6.3.2启动过程源码阅读记录 网上有很多关于es的源码分析,觉得自己技术深度还不够,所以这些文章只是看源码过程中的一个笔记,谈不上分析. 整个启动过程以类名.方法名,按顺序 ...

  3. x264阅读记录-2

    x264阅读记录-2 7. x264_encoder_encode函数-1 查看该函数代码(Encoder.c文件)可以发现,该函数中注释很详细,对编码的整个步骤展示的也相对比较清晰. 在查看具体的代 ...

  4. x264阅读记录-1

    x264阅读记录-1 采用x264版本是x264-snapshot-20060316-2245. 1. main函数 x264的main函数位于x264.c中,下面是main函数调用情况: (1)_s ...

  5. 《Javascript高级程序设计》阅读记录(七):第七章

    <Javascript高级程序设计>中,2-7章中已经涵盖了大部分精华内容,所以摘录到博客中,方便随时回忆.本系列基本完成,之后的章节,可能看情况进行摘录. 这个系列以往文字地址: < ...

  6. 《Javascript高级程序设计》阅读记录(六):第六章 下

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...

  7. 《Javascript高级程序设计》阅读记录(五):第六章 上

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...

  8. 《Javascript高级程序设计》阅读记录(三):第五章 上

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 这个系列,我会把阅读< ...

  9. 《Javascript高级程序设计》阅读记录(一):第二、三章

    <Javascript高级程序设计>阅读记录(一) 这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较深入,而且实际使用价值较大的内容记录下来,并且注释 ...

随机推荐

  1. ProcessList.java和adj值

    简单地讲,adj值决定了在系统资源吃紧的情况下,要先杀掉哪些进程. 在Android的lowmemroykiller机制中,会对于所有进程进行分类,对于每一类别的进程会有其oom_adj值的取值范围, ...

  2. BZOJ 2118 墨墨的等式(最短路)

    很开拓眼界的题.. 题意:给出一个n元一次方程形如a1*x1+a2*x2...+an*xn=B,求满足解集为非负整数的B值在[L,R]范围内的种数.(n<=12,ai<=5e5,L< ...

  3. poj3041 Asteroids(二分图最小顶点覆盖、二分图匹配)

    Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape o ...

  4. C++函数中的那些坑

    平时写程序时,我们可能或多或少对一些用法感到朦胧,下面我对一些易困惑大家,或者易用错的地方作点介绍. 一.函数的一些注意点 1.函数返回类型不能是数组类型或函数类型,但可以是指向数组或函数的指针. 2 ...

  5. 【JavaScript】获取项目路径地址

    在jsp页面顶上面定义 <% String path = request.getContextPath(); String basePath = request.getScheme() + &q ...

  6. 【Java】JAVA开发人员常见环境工具安装

    1.安装配置JDK1.7:jdk-7u45-windows-x64.exe,环境变量配置:JAVA_HOME---[F:\1024\jdk1.7],CLASSPATH---[.;%JAVA_HOME% ...

  7. TCP的拥塞控制 (三)

    1.   Multiple Packet Losses Fast Retransmit/Fast Recovery机制可以很好地处理单个packet丢失的问题,但当大量packet同时丢包时(一个RT ...

  8. 【BZOJ3243】【NOI2013】向量内积(矩阵,数论)

    [BZOJ3243][NOI2013]向量内积(矩阵,数论) 题面 BZOJ 题解 这题好神仙. 首先\(60\)分直接是送的.加点随机之类的可以多得点分. 考虑正解. 我们先考虑一下暴力. 我们把\ ...

  9. 【BZOJ4443】小凸玩矩阵(二分答案,二分图匹配)

    [BZOJ4443]小凸玩矩阵(二分答案,二分图匹配) 题面 BZOJ Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两 ...

  10. 【BZOJ1491】【NOI2007】社交网络(最短路,动态规划)

    [BZOJ1491][NOI2007]社交网络(最短路,动态规划) 题面 BZOJ 洛谷 图片是假的,只能到OJ上看 Description 在社交网络(socialnetwork)的研究中,我们常常 ...