5.7.1

5.7.1 完美散列(Perfect Hashing)

本文是数据结构与算法分析——C++语言描述(Data Structures and Algorithms Analysis in C++)的学习笔记。

完美散列是解决最坏情形 O ( 1 ) O(1) O(1)访问的散列表问题的最早方案。

我们之前介绍过普通的散列表。由于冲突的存在,我们需要使用分离链接法或者开放定址法来改进我们的散列表。使用这两种办法的任意一种后,就不能保证我们访问这些散列表的最坏情形是 O ( 1 ) O(1) O(1)。完美散列完美地解决了这个问题。

考虑比较简单的情形,假设散列表中的元素都是已知的且数目固定为 N N N(这其实也是完美散列的应用前提)。如果我们用分离链接法来解决散列过程中的冲突问题,那么我们很容易得出,链表的数目 M M M越多,那么平均分到每个链表中的元素就会越少,相应的,含有最多元素的链表所含的元素数目也会越少。如果我们使用的链表足够多,那么散列的元素出现冲突的概率就会足够低,我们就无需使用分离链接法或者开放定址法来解决冲突了,此时访问这个散列表的最坏情形便是 O ( 1 ) O(1) O(1)

这种解决方案带来两个问题:一是链表的数目会太多;二是仍然无法完全解决冲突的问题。

第二个问题相对来说比较好解决。我们增加链表的数目,使得散列的元素发生冲突的概率小于 1 / 2 1/2 1/2。此时,如果我们使用一个哈希函数使得散列元素发生冲突,那么我们可以尝试另外一个哈希函数,直到散列中的元素不发生冲突。尝试的期望次数最多为 2 2 2

现在剩下第一个问题需要我们解决:到底需要多少个链表才能使得散列的元素发生冲突的概率小于 1 / 2 1/2 1/2呢?

定理5.2 如果 N N N个球被放入 M = N 2 M=N^2 M=N2个箱子中,那么没有箱子装有多余一个球的概率大于 1 / 2 1/2 1/2

证明:显然,第 i , j i, j i,j个球 ( i , j ≤ N ) (i, j \leq N) (i,jN)发生冲突的概率为 1 / M 1/M 1/M。故存在一对球发生冲突的概率为
C N 2 M = N ( N − 1 ) 2 N 2 < 1 2 \frac{C_N^2}{M}=\frac{N(N-1)}{2N^2}<\frac{1}{2} MCN2=2N2N(N1)<21

由定理5.2知,要想使散列的元素发生冲突的概率小于 1 / 2 1/2 1/2,则链表的个数为 M = Ω ( N 2 ) M=\Omega(N^2) M=Ω(N2)。显然,使用 N 2 N^2 N2个链表是不切合实际的。不过从上面的分析可以提出下面的方案:使用 N N N个箱子,但是通过散列表而不是列表来解决箱子中的冲突。其想法在于,因为我们期望每个箱子只有少数几项,所以每个箱子所用的散列表以箱内项数表示可以是二次的。

在这里插入图片描述

图5.24显示了它的基本结构。这里,主散列表有10个箱子。箱子1、3、5、7都是空的。箱子0、4、8只有一项,从而它们可以借助1个位置的耳机散列表来解决冲突。箱子2和6都有2项,因此它们将通过4个位置的二级散列表来解决。箱子9有三项,因此它将使用带有9个位置的二级散列表。

和原始的想法一样,每个二级散列表都将使用不同的散列函数来避免冲突。如果产生的冲突次数大于要求,那么主散列表还可以构造多次。

这种方法便是完美散列(Perfect Hashing)

现在证明:这些二级散列表的总大小是线性的。

定理5.3 要是将 N N N项放入包含 N N N个箱子的主散列表中,那么二级散列表的总大小的期望值最多为 2 N 2N 2N

证明:

与定理5.2的证明思路相似。成对冲突的期望数最多为 N ( N − 1 ) / 2 N N(N-1)/2N N(N1)/2N。设散列到每一个“箱子”中元素为 b i b_i bi, 那么每个箱子中二级散列表的大小为 b i 2 b_i^2 bi2。每一个箱子中的成对冲突的期望数最多为 b i ( b i − 1 ) / 2 b_i(b_i-1)/2 bi(bi1)/2,记为 c i c_i ci。那么此时总的空位为
M = ∑ b i 2 = 2 ∑ c i + ∑ b i M=\sum b_i^2=2\sum c_i+\sum b_i M=bi2=2ci+bi
成对冲突的期望数最多为 N ( N − 1 ) / 2 N N(N-1)/2N N(N1)/2N,那么有
∑ c i ≤ N − 1 2 \sum c_i \le \frac{N-1}{2} ci2N1

M < 2 ⋅ N − 1 2 + N < 2 N M<2\cdot\frac{N-1}{2}+N<2N M<22N1+N<2N

于是,总的二级空位需求大于 4 N 4N 4N的概率小于 1 / 2 1/2 1/2。我们可以采用之前提到过的策略继续选择哈希函数,且尝试次数的期望值为 1 / 2 1/2 1/2。这些散列表建成之后,任何查找都能在两次探测之内解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值