您的位置:首页 > 编程语言 > Go语言

google hash表之dense_hash

2016-04-13 15:43 525 查看
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 具有紧缩策略。由此猜想,在紧缩过程中,才会将标记删除的元素真正意义上删除(然而,为何要采用标记删除呢?直接删除然后令那个同为空为何不可以)

#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;
}


由于作者水平有限,不足之处恳请指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: