哈希算法
index = hash%length length 一般取素数,以使得求模运算出来的冲突更少(可以提前计算出素数表存起来)
将 key 转换为固定长度数组下标,存取<key,value>。
解决冲突常见方法
当一个索引位置已经存取了某个值,后续通过计算又落到该索引位置时,产生存取冲突,解决方法有:
- 开放地址: 产生冲突时,使用线性探测,向后移动 n 个位置。该方式缺点是容易引发元素聚集。
- 再哈希Rehash:发生冲突时,使用第二个,第三个 hash 函数计算地址(比如取第 n 位),直到无冲突
- 链表: 新加的数据更可能是"热数据",所以将新增加的元素插入链表头部
在编程语言层面,
GoLang和C++unordered_map 使用链表结构.Java HashMap实现默认也是链表,不同的是当 bucket 内链表长度超过 8 的时候转换成红黑树(目的是加快查找)C#使用的是再哈希方式,一次冲突再换一个,直到找到有空位的地方存储。Pythondic{}采取开放地址
装载因子
a = 元素个数/hash数组大小,a 在 0.6~0.9 之间,一般取 0.75. 即当存取元素的数组接近装载满时,重新生成一个新的更大数组并将旧数据导入。