使用一个哈希表来改进另一个哈希表

时间:2015-12-12 21:38:51

标签: data-structures hash hashtable

我正在为我的决赛学习我们的教授给我们的问题。我不知道如何回答这个问题:

考虑具有n个值的散列表T1,其中我们使用f(k)= k%n作为散列函数,使用Chaining作为我们的碰撞解决方法。现在,我们希望使用相同的哈希函数将这些相同的值插入到第二个哈希表T2中,但应用线性探测(Single-Probing)来解决冲突。你怎么能利用T1建立T2?

2 个答案:

答案 0 :(得分:0)

注意:我的答案不包含确切的解决方案,只包含想法。

如果我理解正确,我们已经有一个哈希表实例 T1 ,其中包含 n 值,我们想用它来构建 T2 < / em>,而不是从头开始正常构建 T2

由于 n 存储桶的 n 值,我们知道哈希表将会满。

我的想法#1:

我会循环遍历 T1 的所有存储桶。当我在 m -th存储桶中找到一串值时,我可以知道所有这些值的散列都是 m ,而不必调用散列函数。所以我可以将所有这些值插入 m -th,(m + 1) -th,(m + 2) -th ... T2 中的存储桶,或者如果一个被占用,那么我会跳过该存储桶。

优点是我们永远不必调用哈希函数。

我的想法#2:

我可以看到哪些存储桶包含很多存储区,哪些存储区包含 T1 中很少的元素(如1-2)。我可以使用此信息来确定理想的插入顺序,以最大限度地减少平均访问时间。不幸的是,我想不出一个确定理想订单的具体方法。

实施例

N = 10
values = 10,20,30,40,11,32,13,35,45,19

T1总是看起来像这样(链中的顺序无关紧要):

0 -> {10,20,30,40}
1 -> {11}
2 -> {32}
3 -> {13}
4 -> {}
5 -> {35,45}
6 -> {}
7 -> {}
8 -> {}
9 -> {19}

与T1不同,T2可能会根据值的插入顺序而有所不同。访问每个元素的一个可能的T2需要几个步骤:

0 -> {10} 0 off
1 -> {20} 1 off
2 -> {30} 2 off
3 -> {40} 3 off
4 -> {11} 3 off
5 -> {32} 3 off
6 -> {13} 3 off
7 -> {35} 2 off
8 -> {45} 3 off
9 -> {19} 0 off

另一个可能的T2,当一些元素可以立即访问,但有些元素真的关闭:

0 -> {10} 0 off
1 -> {11} 0 off
2 -> {32} 0 off
3 -> {13} 0 off
4 -> {20} 4 off
5 -> {35} 0 off
6 -> {45} 1 off
7 -> {30} 7 off
8 -> {40} 8 off
9 -> {19} 0 off

答案 1 :(得分:0)

  

...带有 n 值的哈希表T1我们使用 f(k)= k%n < / em> 用于哈希函数和链接作为我们的冲突解决方法。现在,我们希望使用相同的哈希函数将这些相同的值插入到第二个哈希表T2中,但应用线性探测(单一探测)来解决冲突。您如何利用T1构建T2

完全按照要求采取, f(k)= k%n 是一个疯狂的愚蠢哈希函数,如:

  • 我们被告知“n”是值的数量

    • 如果这是真的并且n小于桶的数量,我们会在使用n之后人为地阻止桶;因此,碰撞率将显着高于必要的

    • 因为在更改时插入或删除了元素,所以我们在每次插入或删除每个值时都会对表格进行重新计算是不可想象的

总而言之,假设教授忘了他/她定义了“n”是安全的,并且希望f(k)中的n是桶的数量。

让我们继续......

因为我们知道散列值与存储桶值匹配,所以我们知道从一个存储桶链接的所有值都已经散列到存储桶阵列中该存储桶的索引。我们不需要再次调用f(x)来为相同的#buckets生成另一个哈希。

毫无疑问,教授正在寻找的是:如果用与T1相同数量的桶创建T2,那么你可以在桶索引上运行一个计数器,将所有值复制到T2,从同一个开始存储桶,或者如果正在使用 - 您可以使用线性探测找到下一个存储桶。您还可以保留 next-index-in-T2-that-free-free 变量,这样您就不必逐步执行线性探测已经结束的存储桶。

所以:你可以节省自己的重复k,并用较少重复的探测来处理碰撞。