散列函数之双重散列算法解决冲突问题

本文探讨了散列函数中的冲突问题,特别是针对简单散列算法的“clustering”问题。通过引入双重散列算法,使用两个散列函数h0(k)和g(k)来减少冲突,提高查找效率。文中通过实例展示了双重散列如何处理冲突,以及其冲突概率的分析,证明了双重散列函数相比单散列函数具有更低的冲突率。
摘要由CSDN通过智能技术生成

1. 问题

问题同《简单散列函数算法》,这个例子并不是特别恰当,当在于简单,数字小,方便验证,方便理解,特别是计算概率的部分。

设有10个非负整数,用不多于20个的储存单元来存放,如何存放这10个数,使得搜索其中的某一个数时,在储存单元中查找的次数最少?

问题类似于,有10个带号码的球,放到编号为{0, 1, 2, …, 19}共20个盒子中,每个盒子最多放一个,问如何放,使能够用最少的次数打开盒子,知道任一个球所在的盒子编号?

 

2. 分析

散列函数之单散列算法解决冲突问题》中,我们提到用单散列算法来解决冲突,比简单散列算法冲突的比率有所降低,但18%的冲突率,对于实际应用来说还是略偏高,《初等数论及其应用》中,说明是从另一个角度来说明该冲突率高的原因。

设 h0(k) ≡ k (mod m), k = 球号, m = 盒子数量

hj(k) ≡ h0(k) + j,0<= j < m,  hj(k) 表示发生 j 次冲突后,球所放入的盒子编号

∴ hj+1(k) ≡ h0(k) + (j + 1) ≡ hj(k) + 1

∴ 只要有一个hi(k1) ≡ hj(k2)

则所有的hi+n(k1) ≡ hj+n(k2) (n = {0, 1, 2, …})

用数学归纳法可以很容易的证明

也可以用同余算法如下证明:

hi+n(k1) ≡ h0(k2) + n

∵ hi(k1) ≡ hj(k2)

∴ hi+n(k1) ≡ hj(k2) + n ≡ hj+n(k2)

∴ 只要有一个球对应的盒子编号hi(k1)与另一个hj(k2)冲突,则会有无数对 hi(k1)+n 和 hj(k2)+n  冲突

如《散列函数之单散列算法解决冲突问题》测试的数据中,0和19冲突,则 0+1 = 1 和 19+1 = 20也是冲突的,类似, 2和21, 3和22等等都会冲突,也就是说,只要球号中有对应的连续数列,就特别容易产生冲突,导致该序列查找的次数会剧增,这个问题称为”clustering”,书中《初等数论及其应用》中翻译为堵塞,我觉得翻译为聚集冲突更合适,这是因为简单的加1不能使数字不能足够分散所致。

这里用一组聚集冲突的数据演示一下:

numList = [0, 1, 2, 19, 20, 21, 18, 44, 17, 38, 77];

测试结果发现,所有的连续数列的球号都排在前8个序号的盒子中,冲突的序列都需要4次的查找,而38因为和连续数列的第一个数字同余冲突,导致的查找次数更是达到8次,如果散列函数处理的数据中有如此的序列,那么算法性能会急剧下降。

 

为了解决这个问题,既然有单散列算法,那么自然就想到双散列算法。

 

3. 双重散列算法

双散列算法为了解决单散列算法中 +j 过于连续,不够分散而来,同时能够进一步降低冲突率。其为了进一步分散冲突的数字,对冲突的球的数字再一次进行散列

h0(k) ≡ k (mod m), k = 球号

m = 盒子的数量,m 取接近最大盒子数量的素数

散列函数1 : g(k) ≡ k + 1 (mod m -2)

散列函数2 : hj(k) ≡ h0(k) + j*g(k) (mod m),  hj(k) 表示发生 j 次冲突后,球所放入的盒子编号

注意g(k)的模变了,变为 (m-2),为什么要用这个,一会分析冲突要用

 

4.双重散列生成示例

仍用《散列函数之单散列算法解决冲突问题》中的测试数据{0, 1, 2, 7, 9, 15, 19, 20, 77, 38}

m = 19, m-2 = 17

球号 0 1 2 7 9 15 19 20 77 38
模19余数 0 1 2 7 9
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值