google hash表之dense_hash
2016-04-13 15:43
537 查看
https://github.com/sparsehash/sparsehash
dense_hash 是google的一个开源的hashtable的实现。
可以通过value找到key ExtractKey,支持(反)序列化到文件,现在主要分析非(反)序列化部分
成员变量
Settings settings;
KeyInfo key_info;
size_type num_deleted; // how many occupied (已经占用的)buckets are marked deleted
size_type num_elements;
size_type num_buckets;
ValInfo val_info; // holds emptyval, and also the allocator
pointer table; //typedef typename value_alloc_type::pointer pointer;
其中,元素放在table中,table是一个指向了value值数组的指针。由此使得dense_hash相比较hash_table而言非常节约内存。
每次插入对象的时候,通过find_position函数来找到应该在哪里插入对象,返回对象是一个pair指针,指针第一个元素代表了这个要插入的元素本省的位置,second表示如果想要插入这个元素则应该往哪里插入。
如果first==ILLEGAL_BUCKET:没有找到这个元素,直接返回hash值
如果second==ILLEGAL_BUCKET:表示这个元素本来就是在hash表表中的,对于这个情况的处理方式是:返回迭代器的位置
如果探测到了冲突,则采用二次探测的方式进行下次的探测
++num_probes; // we're doing another probe
bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one;
其中 JUMP_(key, num_probes) 是一个宏定义,估计是还没有实现完全吧。
#define JUMP_(key, num_probes) ( num_probes )
其中, 当表中的已经有的元素和总的空间的占比大于0.8的时候,就进行resize
hashtable预留的元素个数是4,元素的个数值必须是2的,幂次方
采用标记删除的方式来删除元素,标记值由用户来自己定义,就是定义自己的key不可能出现的值,保存在key_info.delkey里面,通过set_deleted_key来进行设置
同时可以由用户来定义什么情况下表示这个元素是空的(这个函数必须要在构造后调用dense_hash的其它函数前就要用上)
dense hash 具有紧缩策略。由此猜想,在紧缩过程中,才会将标记删除的元素真正意义上删除(然而,为何要采用标记删除呢?直接删除然后令那个同为空为何不可以)
由于作者水平有限,不足之处恳请指出。
dense_hash 是google的一个开源的hashtable的实现。
可以通过value找到key ExtractKey,支持(反)序列化到文件,现在主要分析非(反)序列化部分
成员变量
Settings settings;
KeyInfo key_info;
size_type num_deleted; // how many occupied (已经占用的)buckets are marked deleted
size_type num_elements;
size_type num_buckets;
ValInfo val_info; // holds emptyval, and also the allocator
pointer table; //typedef typename value_alloc_type::pointer pointer;
其中,元素放在table中,table是一个指向了value值数组的指针。由此使得dense_hash相比较hash_table而言非常节约内存。
每次插入对象的时候,通过find_position函数来找到应该在哪里插入对象,返回对象是一个pair指针,指针第一个元素代表了这个要插入的元素本省的位置,second表示如果想要插入这个元素则应该往哪里插入。
如果first==ILLEGAL_BUCKET:没有找到这个元素,直接返回hash值
如果second==ILLEGAL_BUCKET:表示这个元素本来就是在hash表表中的,对于这个情况的处理方式是:返回迭代器的位置
如果探测到了冲突,则采用二次探测的方式进行下次的探测
++num_probes; // we're doing another probe
bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one;
其中 JUMP_(key, num_probes) 是一个宏定义,估计是还没有实现完全吧。
#define JUMP_(key, num_probes) ( num_probes )
其中, 当表中的已经有的元素和总的空间的占比大于0.8的时候,就进行resize
hashtable预留的元素个数是4,元素的个数值必须是2的,幂次方
采用标记删除的方式来删除元素,标记值由用户来自己定义,就是定义自己的key不可能出现的值,保存在key_info.delkey里面,通过set_deleted_key来进行设置
同时可以由用户来定义什么情况下表示这个元素是空的(这个函数必须要在构造后调用dense_hash的其它函数前就要用上)
dense hash 具有紧缩策略。由此猜想,在紧缩过程中,才会将标记删除的元素真正意义上删除(然而,为何要采用标记删除呢?直接删除然后令那个同为空为何不可以)
#include <google/dense_hash_map> using std::dense_hash_map; // namespace where class lives by default struct eqstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; } }; int main() { dense_hash_map<const char*, int, hash<const char*>, eqstr> months; months.set_empty_key(NULL); months["january"] = 31; months["february"] = 28; months["march"] = 31; months["april"] = 30; months["may"] = 31; months["june"] = 30; months["july"] = 31; months["august"] = 31; months["september"] = 30; months["october"] = 31; months["november"] = 30; months["december"] = 31; cout << "september -> " << months["september"] << endl; cout << "april -> " << months["april"] << endl; cout << "june -> " << months["june"] << endl; cout << "november -> " << months["november"] << endl; }
由于作者水平有限,不足之处恳请指出。
相关文章推荐
- 从搜索结果中进入Product面包屑也包含Category Path
- Go1.6与JVM CMS的垃圾回收对比
- GoldenGate之目录详解
- Why is try {…} finally {…} good; try {…} catch{} bad?
- VNC Viewer远程登录服务器时 点了logout
- 谷歌推出最新图像识别工具Google Cloud Vision API
- I.MX6 driver goto 使用
- Django中的ORM进阶操作
- Golang开发环境搭建-Vim篇
- Go语言展现快速排序算法全过程的思路及代码示例
- deeplab hole algorithm
- HDOJ 4722Good Numbers 数位DP
- SerialControl.start not connected
- 深入解析快速排序算法的原理及其Go语言版实现
- Django中,模型(models),视图(views)和模板的区别和应用
- mongo按坐标点查询其所在多边形区域
- Google地图开发初级篇
- golang 字符串操作实例
- Google推荐的图片加载库Glide介绍二
- Google推荐的图片加载库Glide介绍(与Picasso比较)一