构造哈希表的几种方法
直接定址法
f(key) = a × key + b
除留余数法
f( key ) = key mod p ( p ≤ m )
mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。
1. 平方取中法
2. 折叠法
3. 随机数法
4. 数学分析法
哈希冲突(碰撞)以及处理
开发定址法
所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
- 线性探测法
f(key) = (f(key)+di) MOD m (di=1,2,3,......,m-1)
用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表中无待查的关键字,即查找失败。
- 二次探测法
f(key) = (f(key)+di) MOD m (di = 1^2, -1^2, 2^2, -2^2,……, q^2, -q^2, q <= m/2)
注:1^2 表示是 1的平方
设哈希表长m=14,哈希函数H(key)=key%11。表中已有4个结点:addr(15)=4,addr(38)=5,addr(61)=6,addr(84)=7,其余地址为空。如果用二次探测再散列处理冲突,关键字为49的结点的地址是?
因为 f(49) = 5 与 f(38) 冲突
所以需要采用二次探测再散列来处理冲突
(f(49) + di) MOD 14(哈希表长m=14)
第一次 di = 1^2
(5 + 1)MOD 14 = 6 与addr(61)=6冲突
第二次 di = -1^2
(5 - 1)MOD 14 = 4 与addr(15)=4 冲突
第三次 di = 2^2
(5 + 4)MOD 14 = 9 没有冲突
所以 addr(49)=9
- 链地址法
前面我们谈到了散列冲突处理的开放定址法,它的思路就是一旦发生了冲突,就去寻找下一个空的散列地址。那么,有冲突就非要换地方呢,我们直接就在原地处理行不行呢?
答案是可以的,就是链地址法,就好比Java里的HashMap的数据结构一样。