解决哈希冲突的三种方法

一 .线性探测

取余数寻址,如果地址被占用继续往后移.比如:
在这里插入图片描述
随之而来的一个问题是:如果后面的数据大多取余之后都是8或者9,hash碰撞就会加剧,一方面导致插入效率降低(我们称之为主集团问题(primary clustering)),另一方面还增大了主集团的面积.由此,引入新的方法.

二. 二次探测

例如如果hash function计算出的新元素位置为H,实际该位置已被使用,那么我们依次尝试H+12,H+22,H+32,… …,H+i2,而不是像线性探测那样依次尝试H+1,H+2,H+3,… …,H+i.如下图为二次探测的一个实例:
二次探测

那么问题来了:
1.线性探测每次探测必然是一个不同位置,二次探测能否保证如此?如果表格中本身没有X,我们插入X是否一定能成功?
如果我们假设表格大小为质数(prime),且永远保持负载系数为0.5以下(也就是说超过0.5就重新配置并重新整理表格),那么就可以确定每插入一个新元素所需要的探测次数不超过2.

2.二次探测相比线性探测较复杂,这是否会降低执行效率?
我们看到二次探测中我们需要做一个乘法和一个除法,然而这里有个小技巧替代这个耗时的乘法和除法:
Hi = H0 + i2(MOD M)
Hi-1 = H0 + (i-1)2(MOD M)
整理得:
Hi - Hi-1 = i2 + (i-1)2(MOD M)
Hi = Hi-1 + 2i - 1(MOD M)
我们可以通过上一个H值推导下一个H,虽然还需要个乘法,但那是2,完全可以通过位运算快速完成.

3.不论线性探测或二次探测,当负载系数(元素个数除以表格大小)过高时,表格能否动态增长?
要扩充表格,首先必须找下一个新的且够大(大约2倍)的质数,然后必须考虑表格重建(rehashing)的成本.我们不可能原封不动的拷贝,必须要检验旧表格中的每个元素,计算其在新表格中的位置,然后再插入到新表格中.

新的问题:二次探测可消除主集团,却可能造成次集团(secondary clustering):2个元素经hash function计算出来的位置若相同,则插入时所探测的位置也相同,形成某种浪费.消除次集团的办法当然也有,例如复式散列(double hashing);虽然目前还没对二次探测有数学上的分析,但以上所有考虑加加减减起来,总体而言二次探测仍值得投资.

三. 开链(separate chaining)

这种做法是在表格每个元素中维护一个list.hash function为我们分配某个list,然后我们在那个list身上执行元素的插入,搜寻,删除等操作,虽然针对list而进行的搜寻只能是一种线性操作,但如果list够短,速度还是够快.
使用开链表格负载系数将大于1. SGI STL的hash table便是采用这种做法.
未完待续…

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值