Data structures 使用一个哈希表改进另一个哈希表

Data structures 使用一个哈希表改进另一个哈希表,data-structures,hash,hashtable,Data Structures,Hash,Hashtable,我正在准备期末考试,教授给了我们一些问题。我不知道如何回答这个问题: 考虑一个具有n个值的散列表T1,其中我们使用f(k)=k%n作为散列函数,并将链接作为冲突解决方法。现在,我们希望使用相同的哈希函数将这些相同的值插入到第二个哈希表T2中,但应用线性探测(单探测)来解决冲突。您如何利用T1构建T2?注意:我的答案中没有确切的解决方案,只有想法 如果我理解正确,我们已经有一个哈希表实例T1,其中包含n个值,我们希望使用它来构建T2,而不是通常从头构建T2 因为n个bucket有n个值,所以我们知

我正在准备期末考试,教授给了我们一些问题。我不知道如何回答这个问题:


考虑一个具有n个值的散列表T1,其中我们使用f(k)=k%n作为散列函数,并将链接作为冲突解决方法。现在,我们希望使用相同的哈希函数将这些相同的值插入到第二个哈希表T2中,但应用线性探测(单探测)来解决冲突。您如何利用T1构建T2?

注意:我的答案中没有确切的解决方案,只有想法

如果我理解正确,我们已经有一个哈希表实例T1,其中包含n个值,我们希望使用它来构建T2,而不是通常从头构建T2

因为n个bucket有n个值,所以我们知道哈希表将满

我的想法#1: 我将遍历T1的所有桶。当我在第m个bucket中找到一个值链时,我可以知道所有这些值的散列都是m,而不必调用散列函数。所以我可以把所有这些值都插入到m-th,(m+1)-th,(m+2)-th。。。T2中的桶,或者如果一个被占用,那么我跳过该桶

优点是我们永远不需要调用哈希函数

我的想法2: 我可以看到T1中哪些bucket包含很多元素,哪些bucket包含很少的元素(比如1-2)。我可以使用这些信息来确定理想的插入顺序,以最小化平均访问时间。不幸的是,我想不出一个具体的方法来确定一个理想的顺序

例子: T1总是这样(链中的顺序无关紧要):

与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
另一种可能的情况是,某些元素可以立即访问,但某些元素确实关闭:

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

注意:我的答案中没有确切的答案,只有想法

如果我理解正确,我们已经有一个哈希表实例T1,其中包含n个值,我们希望使用它来构建T2,而不是通常从头构建T2

因为n个bucket有n个值,所以我们知道哈希表将满

我的想法#1: 我将遍历T1的所有桶。当我在第m个bucket中找到一个值链时,我可以知道所有这些值的散列都是m,而不必调用散列函数。所以我可以把所有这些值都插入到m-th,(m+1)-th,(m+2)-th。。。T2中的桶,或者如果一个被占用,那么我跳过该桶

优点是我们永远不需要调用哈希函数

我的想法2: 我可以看到T1中哪些bucket包含很多元素,哪些bucket包含很少的元素(比如1-2)。我可以使用这些信息来确定理想的插入顺序,以最小化平均访问时间。不幸的是,我想不出一个具体的方法来确定一个理想的顺序

例子: T1总是这样(链中的顺序无关紧要):

与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
另一种可能的情况是,某些元素可以立即访问,但某些元素确实关闭:

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

正如所问,f(k)=k%n是一个极其愚蠢的哈希函数,如下所示:

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

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

    • 当元素被插入或删除或更改时,不可想象我们会在每次插入或删除单个值时重新刷新表

总而言之,可以安全地假设教授忘记了s/他定义的“n”,并希望f(k)中的n是桶数

让我们一起跑吧

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

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

因此:您可以避免重新使用
k
,并以较少的重复探测来处理冲突

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

正如所问,f(k)=k%n是一个极其愚蠢的哈希函数,如下所示:

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

    • 如果这是真的并且
      n
      小于