Data structures 哈希表在发生冲突时如何读取正确的值?

Data structures 哈希表在发生冲突时如何读取正确的值?,data-structures,hashtable,Data Structures,Hashtable,我有一些哈希表。例如,我有两个实体,比如 john = { 1stname: jonh, 2ndname: johnson }, eric = { 1stname: eric, 2ndname: ericson } 然后我把它们放在哈希表中: ht["john"] = john; ht["eric"] = eric; 让我们假设有一个冲突,哈希表使用链接来修复它。因此,应该有一个包含这两个实体的链表,如下所示 哈希表如何理解应该为键返回什么实体?散列值是相同的,它对实体结构一无所知。例如,如

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

john = { 1stname: jonh, 2ndname: johnson },
eric = { 1stname: eric, 2ndname: ericson }
然后我把它们放在哈希表中:

ht["john"] = john;
ht["eric"] = eric;
让我们假设有一个冲突,哈希表使用链接来修复它。因此,应该有一个包含这两个实体的链表,如下所示
哈希表如何理解应该为键返回什么实体?散列值是相同的,它对实体结构一无所知。例如,如果我写这个
var val=ht[“john”]哈希表(只有键值和它的散列)如何发现值应该是john记录而不是eric

这是您想要的吗?我已经把这个放在评论里了,但在我看来你们并没有关注这个链接

哈希表类中的冲突解决方案

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

  • 线性探测
  • 四次探测
Hashtable类使用了一种称为重新调整的不同技术。(一些来源将重新哈希称为双重哈希。)

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

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

数学注释在进行重新置位时,在进行hashsize数量的探测时,必须精确访问哈希表中的每个插槽一次。也就是说,对于给定的键,您不希望Hi和Hj散列到散列表中的同一个插槽。对于Hashtable类使用的重新灰化公式,如果
(1+(((GetHash(key)>>5)+1)%(hashsize–1))
和hashsize的结果是相对素数(如果两个数字没有公共因子,则它们是相对素数),则会维护此属性如果hashsize是素数,则这两个数保证是相对素数。 与线性或二次探测相比,重新定位提供了更好的碰撞避免


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

一旦您请求
ht['john']
,哈希表将查找与
hash('john')
相关联的列表,如果列表不为空,它将在列表中搜索键
'john'
。如果找到键作为元组的第一个元素,则查找值(元组的第二个元素)如果找不到键,则表示元素不在哈希表中


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

看看在复杂对象的情况下键相等性是如何工作的?哈希表中的值是一个具有不同pr的对象属性,但您只使用键来获取它。哈希表不知道对象结构,也不知道我使用这个对象的什么属性作为键。看起来我已经得到了。我想哈希表应该将完整键和整个对象放在一起,以定义这个键是否等于所需键,对吗?正如我在回答中提到的,该键与obje一起存储哈希表中的ct:(键,值)。在您的情况下,键是值的一部分,但情况并非总是如此。因此哈希表在找到您搜索的键之前根本不关心您的值。然后它返回关联的值,而不进行任何分析。此外,我开始阅读c#dictionary的源代码,我看到它将键与内在价值。