繁体   English   中英

哈希过程如何在Dictionary中工作<TKey, TValue>

[英]How does the process of hashing work in Dictionary<TKey, TValue>

字典中的哈希处理如何工作? 我读到使用字典可以更快地查找。 但是不明白怎么办? 哈希和映射到索引如何发生? 找不到任何好的参考。

编辑:如何从哈希函数的结果中获取存储对象的实际内存位置?

哈希表或字典是一种存储键-值对的数据结构。 哈希表的优点在于,给定键找到对应的值非常快。 简化后,在哈希表中查找键值对的时间并不取决于表的大小。 将其与将键值对存储在列表或数组中进行比较。 要查找键值对,您必须从头开始搜索列表,直到找到匹配的键。 列表越长,找到键值对所需的时间就越多。 使用big-O表示法可以说,在哈希表中查找键的顺序为O(1),而通过线性搜索在列表中查找键的顺序为O(N)(简化)。

要将键值对插入哈希表中,您首先必须计算键的哈希码。 在.NET中,所有对象都有一个名为GetHashCode的方法,该方法返回该特定对象的哈希码(32位整数)。 相等的对象返回相同的哈希码很重要,但是如果不同的对象返回不同的哈希码,这也非常有用。 注意不要误认为不同的对象不能返回相同的哈希码-它们可以,但是会导致冲突 (请参阅下文)。

例如,考虑两个字符串的哈希码:

"Boo" 0x598FD95A
"Foo" 0x598FD8DE

即使字符串非常相似,它们也具有不同的哈希码。

我在这里简化一些事情,以关注哈希表的重要方面,因此,现在让我们说,Internally Dictionary<TKey, TValue>将键值对存储在数组中。 要在将键值对存储在此数组中的索引中找到索引,您必须以数组大小为模来计算键的哈希码。 假设数组的大小为5:

Index("Boo") = 0x598FD95A % 5 = 4
Index("Foo") = 0x598FD8DE % 5 = 0

这导致此内部哈希表数组:

+---+---------+
| 0 | "Foo"   |
+---+---------+
| 1 | (empty) |
+---+---------+
| 2 | (empty) |
+---+---------+
| 3 | (empty) |
+---+---------+
| 4 | "Boo"   |
+---+---------+

在哈希表中查找条目非常快。 您只需要以内部数组的大小为模来计算键的哈希码,然后在该索引处检索字符串。

现在考虑键“ Zoo”:

Index("Zoo") = 0x598FDC62 % 5 = 0

它具有与键“ Foo”相同的索引。 这导致所谓的碰撞 哈希表的正确实现将必须处理冲突,并且这样做不同的策略 同样,随着内部数组的填充,数组中的空白元素将越来越少,从而导致冲突数量增加。 负载系数是内部阵列中已用元素与总元素之间的比率。 在上面的示例中,负载系数为2/5 = 0.4。 当负载因子超过特定阈值时,大多数哈希表实现都会增加内部数组的大小。

如果您想更多地了解其中一些概念,则必须研究与其他答案相关联的一些更全面的资源。

词典中的哈希处理使用一种称为链接的技术。 通过链接,辅助数据结构可用于保留任何冲突。 具体来说,字典中的每个广告位都有一个映射到存储桶的元素数组。 在发生碰撞的情况下,碰撞元素位于铲斗列表的前面。

有关更多详细信息,请参见MSDN上的这篇文章。

通过使用称为哈希图的计算机科学概念。 这确实比搜索列表更快。 通过使搜索不再需要遍历列表直到找到匹配项,该方法可以起作用。 相反,键是“ 散列的 ”,并用作列表的索引。 该散列函数几乎总是比搜索列表更快(使用多个比较进行迭代)。

通常,通过获取哈希值%数组大小,可能会产生冲突。

正如我试图在回答其他问题时所解释的那样,字典使用哈希键进行查找。 因此,如果您有一个自定义对象类型作为键,那么一切都取决于自定义对象的GetHashCode()实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM