合法关键码数量为R,散列表长为M
散列函数设计
除余法
取M为素数,hash(key) = key % M
MAD法
取M为素数,hash(key) = (a × key + b) % M,a,b皆正,a % M != 0
相较于除余法有更好的均匀性
数字分析法
取key中的若干位
平方取中法
取key²中的若干位
折叠法
将key分为若干段,各段之和作为hash(hey)
位异或法
将key分为若干段,各段之异或作为hash(hey)
伪随机数法
hash(key) = rand(key) % M
- 可移植性差
散列冲突解决
- 开:使用新的存储结构
- 闭散列:不使用新的存储结构
- 封闭:某个散列地址只能由散列值匹配的关键词装入
- 开放地址:无所谓散列值
开散列(封闭地址)策略
多槽位法
散列表每个桶都能装N个关键词
独立链法
散列表每个桶都能装若干关键词,List组织
公共溢出区法
另设一个溢出区,整个散列表一旦冲突就进入溢出区
闭散列(开放地址)策略
装填因子最好小于50%
线性试探法
第k次试探的偏移量为k
- 每次往后找1个
- 聚集现象严重
查找链与平均查找长度
查找链:查找过程中经过的桶(是一条查找路径)
查找长度:尝试匹配的桶的数量
懒惰删除
直接删除导致查找链断裂
标记这个桶曾经有关键码来过,现在是空的
- 既然是空桶,正常插入
- 之前有关键码,查找需要再往后看
平方试探法
第k次试探的偏移量为k²
- 更好的减缓聚集现象
- 装填因子 <= 50%时必能插入
对于素数p,所有的完全平方数模p同余有且只有⌈p / 2⌉个同余类,即
。
- TableSize一定是奇数
- 使用鸽笼原理得知:因装填因子 <= 50%,互异备选位置中一定有空桶
- 如果M不是素数,即使装填因子 < 50%也不一定就能插入
- 如果装填因子 > 50%,即使有空桶也不一定就能插入
- 如果在⌈p / 2⌉次试探后仍未插入,那么不能插入
- 如果在⌈p / 2⌉次试探后仍未插入,那么不能插入
双向平方试探法
偏移量为1,-1,4,-4,9,-9,...
- 如果M是形如4k + 3的素数,那么前M次试探桶必然互异
- 反之,如果M取作4k + 1的素数,那么必然不能保证前M次试探均互异
- 换言之,这将遍历整个散列表,只要还有空桶,必能插入
伪随机试探法
如果第k次冲突,就尝试地址为rand(k) % M的桶,直到找到一个空桶
双散列法
第k次试探的偏移量为k × hash_2(key)
- 每次往后找hash_2(key)个
再散列
类比向量扩容,容量翻倍,数据搬迁