哈希表如何在碰撞时读取正确的值?

时间:2017-01-17 12:27:44

标签: data-structures hashtable

我有一些哈希表。例如,我有两个实体,如

john = { 1stname: jonh, 2ndname: johnson },
eric = { 1stname: eric, 2ndname: ericson }

然后我把它们放在哈希表中:

ht["john"] = john;
ht["eric"] = eric;

让我们假设有一个碰撞和哈希表使用链接来修复它。因此,应该有一个包含这两个实体的链表,如enter image description here 哈希表如何理解应该为密钥返回什么实体?哈希值是相同的,它对实体结构一无所知。例如,如果我写这个var val = ht["john"];哈希表(只有键值及其哈希值)如何发现该值应该是 john 记录而不是埃里克。< / p>

3 个答案:

答案 0 :(得分:13)

我认为您感到困惑的是存储在哈希表相邻列表中每个位置的内容。您似乎假设只存储了值。实际上,每个列表节点中的数据都是元组(键,值)。

一旦您要求ht['john'],哈希表就会找到与hash('john')相关联的列表,如果列表不为空,则会在列表中搜索密钥'john'。如果找到键作为元组的第一个元素,则返回值(元组的第二个元素)。如果找不到密钥,则表示该元素不在哈希表中。

总而言之,密钥哈希用于快速识别元素应存储的单元格(如果存在)。测试实际密钥相等以确定密钥是否存在。

答案 1 :(得分:1)

这是你要求的吗?我已经把它放在评论中,但在我看来你没有关注链接

Hashtable类中的碰撞解决方案

回想一下,当在哈希表中插入项目或从哈希表中检索项目时,可能会发生冲突。插入项目时,必须找到一个打开的插槽。检索项目时,如果实际项目不在预期位置,则必须找到该项目。之前我们简要介绍了两种共谋解决策略:

  • 线性探测
  • Quardratic探测

Hashtable类使用另一种称为rehasing的技术。 (有些消息来源称重新散列为双重散列。)

Rehasing的工作原理如下:有一组哈希不同的函数,H1 ... Hn,当从哈希表中插入或检索项时,最初使用H1哈希函数。如果这会导致碰撞,则尝试使用H2,如果需要,则转到Hn。上一节仅显示了一个哈希函数,即初始哈希函数(H1)。其他散列函数与此函数非常相似,仅通过乘法因子进行区分。通常,散列函数Hk定义为:

Hk(key) = [GetHash(key) + k * (1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1)))] % hashsize

数学注释通过重新定义,当进行hashsize探测次数时,哈希表中的每个插槽都必须访问一次。也就是说,对于给定的密钥,您不希望Hi和Hj散列到散列表中的同一个槽。使用Hashtable类使用的rehashing公式,如果(1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1))和hashsize的结果相对为prime,则会保留此属性。 (如果它们没有共同的因素,则两个数字相对为素数。)如果hashsize是素数,则这两个数字保证是相对素数。 Rehasing提供比线性或二次探测更好的避免碰撞。

sources here

答案 2 :(得分:0)

你的问题没有多大意义。正如您已经指出的,哈希表只知道它的键和值。因此,价值具有何种结构并不重要。

对于通常支持的同一个密钥具有多个值,但也取决于实现。您总是可以使用数组或类似的东西来使值保持多个“事物”。

散列是在密钥上完成的。在您的示例中,哈希是从字符串“john”和“eric”构建的。名为johneric的对象仅存储为值。您的val的赋值示例还将计算字符串“john”中的哈希值,并使用该哈希值查找哈希表中的关联值并将其返回。结构本身,因为哈希应该是每个键唯一的,不应该有冲突。如果是这样,取决于它的处理方式的实际实现。您没有包含您正在使用的语言的任何参考。

这是一个python示例:

# These are already dictionaries themselves
eric = {"Fistname": "Eric", "Lastname": "Johnson"}
john = {"Fistname": "Johnson", "Lastname": "Johnson"}
sarah = {"Fistname": "Sarah", "Lastname": "Doe"}

personbylastname = {}
personbylastname["doe"] = sarah
personbylastname["johnson"] = eric
# The hashmap now has the keys doe and johnson and computed the hashes for them.

try:
    personbylastname["johnson"] += john
except TypeError as e:
    print("This won't work: ",e)
    # There is no defined behavior for adding a dict and a dict.
    # If you do a straight assignment the value is replaced.

personbylastname["doe"] = [sarah]
personbylastname["johnson"] = []
personbylastname["johnson"] += eric,
personbylastname["johnson"] += john,

# This would mean the value would be an empy list.
# Adding a dict to a list would add its keys instead of values
# hence you either need to create a list that contains the dict
# or a tuple that contains the list.

print("Eric: ",personbylastname["johnson"][0])