双散列法:为什么rehash(key)函数值要与散列表的容量tablesize互质?

采用双散列法进行元素的插入与搜索时,要求rehash(key)这个函数值与散列表容量tablesize互质。

个人认为原因如下:

1.(关于rehash()函数简单介绍)

rehash()函数的作用:当在散列表中搜索key关键码时,首先用hash()函数计算hash(key)的值H0,找到下标为H0的位置,若此位置上已有其他元素,则称发生冲突,此时用rehash()函数计算rehash(key)的值r(此值还要求小于tablesize),使Hi=(H(i-1)+r)%tablesize(寻找下一个位置)(tablesize代表散列表的总容量)重复此操作直到下标为h的位置满足条件(若在进行插入操作,则h位置为空即满足条件;若在进行搜索操作,则h位置的元素与key值相同即满足条件)。

2.(需要用到的公式)

(A+B)%m=(A%m+B%m)%m。(证明详见文末)

3.(核心部分:反证)

现有一散列表s[m](容量为m)。假设现在需要对key值进行搜索,那么按照标准散列表步骤,先计算h0=hash(key),此时如果s[h]的值与key值不相等,那么就该rehash()上场了:计算r=rehash(key)(r是小于tablesize的)。若r与m不互质,即存在公共因数(除了1),不妨记作:

r=u*q;  m=v*q; (显然v<m)

令h1=(h0+r)%m,

那么h2=(h1+r)%m=((h0+r)%m+r)%m=((h0+r)%m+r%m)%m=(h0+2*r)%m(这里用到了第二步的公式,其中r=r%m是因为r小于m)。以此类推,hn=(h0+n*r)%m。

如果运气很坏,始终没有能够搜索到key值,那么最多需要遍历m次(也就是把散列表全部搜索一遍),

那么在r和h0有公因数的情况下,能否做到遍历散列表中所有的位置呢?

答案是:不能。

根据之前得到的hn=(h0+n*r)%m。当n=v时(v为m的因数),hn=(h0+v*u*q)%m=h0%m+v*q*u%m=h0,说明当遍历了v个位置后,hn又回到了h0,如果继续遍历下去,可以想象应该是之前遍历的循环,也就是说这种遍历最多只能遍历v个位置,而相应地则有m-v个位置永远无法被遍历到,那么显然这种方法是存在问题的,故而r和m不能有公因数。

4.(正证)

由上可知,hn=(h0+n*r)%m。若m与r互质,那么只有当n=m时,hn=h0%m+m*r%m=h0,也就是说,恰好遍历m个位置才会回到h0,这样就可以实现遍历表中所有的位置,岂不妙哉。

5.(关于第二步中公式的证明)

设A%m=a2; B%m=b2;

则A=a1*m+a2; B=b1*m+b2.

(A+B)%m=(a1*m+a2+b1*m+b2)%m=((a1+b1)*m+(a2+b2))%m=(a2+b2)%m=(A%m+B%m)%m。(证明完毕)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值