算法导论 11.3 散列函数 习题解答

11.3 散列函数

11.3-1 假设我们希望查找一个长度为n的链表,其中每一个元素都包含一个关键字k并具有散列值h(k)。每一个关键字都是长字符串。那么在表中查找具有给定关键字的元素时,如何利用各元素的散列值呢?

搜索过程:

在搜索具有特定长字符字符串的元素时:

计算给定长字符字符串的哈希值。

从与该哈希值相关联的链表的开头开始。

对于链表中的每个元素:

检查当前元素的哈希值是否与从搜索关键字计算得到的哈希值匹配。

如果哈希值匹配,则执行长字符字符串的详细比较以确认匹配。

如果哈希值不匹配,则移动到链表中的下一个元素。

运行时间的影响:

在搜索过程中使用哈希值有助于通过哈希值快速识别潜在匹配项,从而缩小搜索空间。

然而,长字符字符串的详细比较仍然是必要的,而这一步骤可能需要更长的时间,特别是如果长字符字符串很大。

对运行时间的影响与长字符字符串的长度成正比,因为详细的字符串比较涉及检查存储和搜索字符串中的每个字符。

11.3-2 假设将一个长度为r的字符串散列到m个槽中,并将其视为一个以128为基数的数,要求应用除法散列法。我们可以很容易地把数m表示为一个32位的机器字,但对长度为r的字符串,由于它被当作以128为基数的数来处理,就要占用若干个机器字。假设应用除法散列法来计算一个字符串的散列值,那么如何才能在除了该串本身占用的空间外,只利用常数个机器字?

选择一个适当的 m(槽的数量):这通常是一个质数,以减少冲突的可能性。

初始化哈希值为 0:开始时,哈希值为 0。

迭代每个字符:对于字符串中的每个字符,更新哈希值。

hash=(hash * 128 + ascii_value_of_current_char) mod m

这里 ascii_value_of_current_char 是当前字符的 ASCII 值。

11.3-3 考虑除法散列法的另一种版本,其中h(k) = k mod m,m = 2^p - 1,k为按基数2^p表示的字符串。试证明:如果串x可由串y通过其自身的字符置换排列导出,则x和y具有相同的散列值。给出一个应用的例子,其中这一特性在散列函数中是不希望出现的。

归纳假设:要证明每个字符串哈希到其数字和对2p - 1取模的结果。使用归纳法,假设对于长度小于当前字符串长度的所有字符串都成立。

基本情况:假设字符串只有一个字符。那么这个字符的哈希值就是它的数字值对2p - 1取模。也就是说,h(单字符) = 字符值 mod (2p - 1)

归纳步骤:假设对于长度为 |w1w2| 的字符串 w,其中 |w1| >= 1 且 |w2| = 1,成立: h(w) = (h(w1) * 2^p + h(w2)) mod (2p - 1)  其中 h(w1) = k1。

归纳结论:考虑字符串 w = w1w2。由归纳假设,我们知道 h(w1) = k1,表示 w1 的哈希是其数字和对 2p - 1 取模的结果。现在,我们想计算 w 的哈希值。根据归纳步骤,我们有:

h(w) = (h(w1) * 2^p + h(w2)) mod (2p - 1)

将 h(w1) 的值代入:

h(w) = (k1 * 2^p + h(w2)) mod (2p - 1)

这表示 w 的哈希值等于 w1 的哈希值乘以 2^p\) 加上 w2 的哈希值再对 2p - 1 取模。这与我们的归纳假设一致,因此结论成立。

(左移 p 位相当于乘以 2^p,这是引入的权重因子。这个权重因子可以使得 w1 的哈希值的贡献在哈希结果中更显著,与 w2的哈希值的贡献区分开来。)

11-3.4 考虑一个大小为m = 1000的散列表和一个对应的散列函数h(k) = floor(m*((k*A) mod 1)),其中,A = (√5 - 1)/2,试计算关键字61、62、63、64和65被映射到的位置。

700, 318, 936, 554, 172

11.3-5 定义一个从有限集合U到有限集合B上的散列函数簇H为e全域的,如果对U中所有的不同元素对k和l,都有

Pr{h(k) = h(l)} <= e

其中概率是相对从函数簇H中随机抽取的散列函数h而言的。试证明:一个e全域的散列函数簇必定满足:

e >= 1/|B|-1/|U|

使用反证法证明。

反证法的思路:假设存在一个 e 全域的散列函数簇,但不满足上述不等式。

假设条件:假设 e < 1/|B|-1/|U|。

考虑概率不等式:我们知道 e 全域的定义是对于任意两个不同的元素对 k 和 l,都有

Pr{h(k) = h(l)} <= e

使用概率不等式:我们考虑对于所有的 b ∈ B,以及对于每一对不同的元素k, l ∈ U,都有:

Pr{h(k) = h(l) and h(k) = b} <= e

应用全概率公式:使用全概率公式:

Pr{h(k) = b} = 求和Pr{h(k) = h(l) and h(k) = b} (所有可能的k)

简化不等式:由于我们已经有 e < 1/|B|-1/|U|,我们可以继续简化:

Pr{h(k) = b} <= e < 1/|B|-1/|U|

不等式推导:进一步,我们可以得到:

|U| * Pr{h(k) = b} <= |U| * e < |B|-1

矛盾:但这与 e全域的定义矛盾,因为 |U| * Pr{h(k) = b}应该大于等于 |B| - 1,任何一个 b 都至少被 |U| - 1 个不同的元素映射到。

因此,我们的假设 e < 1/|B|-1/|U| 不成立。

11.3-6 设U为取自Z_p中的值构成的n元组集合,并设B = Z_p,其中p为素数。对于一个取自U的输入n元组<a0,a1,...,an-1>,定义其上的散列函数h_b:U --> B (b∈Z_p)为:

h_b(<a0,a1,...,an-1>) = 求和a_j*b^j (j:0 --> n - 1) mod p

并且设H = {h_b:b∈Z_p}。根据练习11.3-5中e全域的定义,证明H是((n-1)/p)全域的。

首先,我们回顾一下 e 全域的定义。一个散列函数簇 H 被称为((n−1/p))全域的,如果对于所有不同的 x,y∈U,都有:

Pr{h(x) = h(y)} ≤ (n−1)/p

其中概率是相对于从函数簇 H 中随机选择一个散列函数 h_b​ 而言的。

现在,我们来证明 H 是((n−1/p))全域的。对于任意两个不同的 x=〈a0​,a1​,…,an−1​〉 和 y=〈b0​,b1​,…,bn−1​〉,我们考虑它们的散列值 h_b(x) 和h_b(y)。

定义 h_b(x) 和 h_b(y) 如下:

h_b(x)=∑j=0 to n−1​a_j * b^j mod p

h_b(y)=∑j=0 to n−1​b_j* b^j mod p

现在,我们将这两个散列值的差异进行分析。考虑 h_b(x)− h_b(y):

 h_b(x)− h_b(y) = ∑j=0 to n−1​(a_j − b_j) * b^j mod p

注意,因为 x 和 y 是不同的元素,至少存在一个下标 i 使得 a_i != b_i​。假设 i 是第一个这样的下标。

h_b(x) − h_b(y)=∑j=0 to i−1 (a_j​− b_j) * b_j + ∑j=i to n−1​(a_j​− b_j) * b_j mod p

=(a_i​− b_i) * b_i + ∑j=i+1 to n−1​(a_j​− b_j) * b_j mod p

≥(a_i​− b_i) * b_i mod p

>−p

这是因为a_i != b_i,所以a_i​− b_i​不等于零,而 b_i 是模 p 意义下非零的。

接下来,我们考虑计算 h_b(x) − h_b(y) 的绝对值:

|h_b(x) − h_b(y)∣ ≤ p−1

将这两个不等式结合起来:

因此,我们可以说 ∣h_b(x) − h_b(y)∣ 至多为 p−1。

现在,考虑一个 b 的值,使得 h_b(x) − h_b(y),那么至少有一个 b 使得 ∣h_b(x) − h_b(y)∣≥1。考虑到 b 的取值范围是 {0,1,…,p−1},我们知道至多有 p−1 个不同的值,其中 h_b(x) != h_b(y)。

因此,我们有:

Pr{h(x)=h(y)} ≤ (p−1)/p​=1 − 1/p​

由于 p 是素数,1/p是一个正数。所以:

Pr{h(x)=h(y)} ≤ (p−1)/p​=1 − 1/p <= (n-1)/p

这证明了 H 是 ((n−1)/p) 全域的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值