khash/flat hash map/unordered_map/map总结

Klib - C语言通用库
Double Hashing(双重hash)
C语言 | #运算符与##运算符
Klib之khash学习笔记
深入解读Khash.h
C语言实战课-klib库学习
罗宾汉哈希
为什么hashtable中桶的数目都是用质数表示
HashMap初始容量为什么是2的n次幂及扩容为什么是2倍的形式?
I Wrote The Fastest Hashtable

对于最后一篇做总结:
flat_hash_map:
1、开放定址法
2、线性探查
3、罗宾汉哈希
4、哈希表大小为质数或者2的幂
5、设置线性探查上限(关键)

1、开放定址意味着hash表的底层就是一个数组
2、线性探查意味着哈希冲突时线性检测下一个桶(线性探查当此时位置为最后一个桶且非空时,会检测边界然后从头开始探查)
3、罗宾汉哈希的目的在于使得各个元素的移动次数均衡,也就是劫富济贫,每个元素在放置时需要记录线性探查的距离,当前元素在遍历到某个非空位置时,会比较他们之间的线性探查距离,如果当前元素的线性探查距离大于等于非空位置元素的线性探查距离,那么就把当前元素放到这个非空位置,把非空位置上的元素重新线性探查下一个位置。
4、哈希表大小为质数的好处在于假设4个桶,元素皆为偶数1,4,6,8,10,12,14,1,6,18,20,22,除留余数法那么就会得到只有0桶和2桶有值(这里假设是开链法),但如果是3个桶那么分布就会更平均

5、设置线性探查上限,当线性探查一定次数时就认定此时需要重新分配表,目的是减少后来元素插入的冲突,设置值为4,n为桶的个数,这对于桶数少元素少的情况有用,但是对于大型的hash表例如1000个桶,随机生成元素,可能会出现表还很空的时候,出现超出线性探查的情况。这样的缺点就是rehash的次数过多,造成时间浪费。

所以设置为log2n,实验发现当元素是随机值时,往往表到2/3的时候才rehashing,当放入连续数字时也可以填满这个表。

作者在实验时将增长因子设置为0.5,为的是当表中插入1000数字然后删掉少量个数字,再插入少量个数字时不会发生rehashing。

但是这个值可以是小于1的任何值,最好不是1,当为1的时候意味着可能会出现表除了最后一个桶都是满的,而且每个元素都是hash得到的位置,此时插入一个数字,与第一个比较会触发罗宾汉导致放入数字取出原数字,然后继续这个流程,这样元素就会不断地变动位置,影响时间。因此还是要准备更多地空桶(注意这里不会触发线性探查上限,因为每个数字只探查了一次)

还做了一个trick来避免边界检测(就是之前提到的最后一个桶满但又有新值来的时候需要回到开头,这样检测边界和从头开始探查都是消耗),假设需要1000个桶,由于质数所以会分配1009个桶,此时探查上限为10(log2(1009)),此时多分配10个桶(也就是1019个),但是对于hash函数外部而言还是只有1009个桶,那么当出现上述情况时,不需要rehash也不需要边界检测就可以分配要放在1008的值,可以直接放在1009。由于探查上限限制导致永远不可能出现有值需要放在超过1018的位置。否则就已经发生rehash了,不需要边界检测

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值