【问题标题】:Interview Questions relating to Hashtable & DictionaryHashtable和字典相关的面试问题
【发布时间】:2011-06-22 19:22:56
【问题描述】:

我最近在一些关于 Hashtables 的采访中得到了训练,什么时候需要覆盖 GetHashCode()。讨论越来越深入,直到我认输。

我现在正在做一些研究,以涵盖为下次准备的所有内容。

我发现了这篇优秀的文章,我想分享: http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx#datastructures20_2_topic5

1) 我觉得不太舒服的是字典是基于哈希的,但列表显然不是。这是否仅意味着在 List 和 Array[] 中搜索是线性的,而在字典或哈希表中搜索是恒定的,因此要快得多?就这些了吗?

2) 如果我使用类作为字典中的键,我需要根据任何必需的标识字段覆盖该类上的 GetHashcode() 以使实例唯一。但是,仍然可能发生两个 ID 字段相等并且会生成相同的哈希码的情况?如果是这种情况,在具有相同哈希码的两个实例发生冲突时会发生什么?

3) 碰撞如何解决?我在文章中读到了关于哈希表冲突和字典链接的重新散列方法。但我仍然不确定它是如何工作的,因为我不是数学天才。 :-\ 谁能更好地解释它是如何工作的?

非常感谢, 卡夫

【问题讨论】:

  • 如果生成相同的哈希码,则在对象上运行 equals 函数以确定相等性。所以不要忘记也覆盖该函数。
  • 我只想感谢所有做出贡献的人。我接受了一次采访,他们要求 HashSet 哈哈。正如我们讨论的那样,我一口气给了他所有哈希的赞成/反对意见,他印象深刻。通过了面试。所以一定是对的。 ;)

标签: .net


【解决方案1】:

1) 通常,是的,Dictionary<T>HashSet<T> 具有恒定时间访问权限。在未排序的List<T> 或数组中定位项目必须线性完成。排序后的集合让您可以进行二分搜索,访问时间为 O(log n)。

2) 如果您在 .NET 中重写 GetHashCode,您还应该重写 Equals 方法。在 .NET DictionaryHashSet 中,您不能插入相等的项目。在一般情况下,哈希冲突是不可避免的(除非您已经计算出完美的哈希)。有几种方法可以解决冲突。

3) 有关冲突解决的更多信息,请参阅http://en.wikipedia.org/wiki/Hash_table

【讨论】:

  • 特别是在 .net 中,通过将链表附加到存储桶来解决冲突
  • 非常感谢您的回答。再往下,我已经对史蒂文的回答写了评论,很可能也会问你。 :) 既然你提到了完美的哈希,我会通过使用数据库中的 100% 唯一主键来实现它吗?哈希冲突是否属于开发人员的责任,还是无论如何都会自动处理?
  • 假设您的数据库中有 1,000 个唯一键,而您的哈希表可以保存其中的任何 100 个键。您创建的哈希码将由哈希表映射到这 100 个插槽之一。因此,即使您的哈希码是唯一的,您也可能在哈希表中发生冲突。最低限度的完美哈希仅在哈希码与哈希表中的槽之间存在一对一映射时才有效。开发人员有责任定义一个散列函数以提供合理的均匀分布,但冲突解决是散列表实现的责任。
【解决方案2】:

哈希表是一种数据结构。更多信息可以在when looking for more general information找到。

1) 列表中的默认搜索是线性的(需要遍历所有元素)。完美的散列(无冲突)允许在最坏的情况下进行恒定时间查找。更多的冲突会导致查找速度变慢。

2) 当散列大量可能键的随机子集时,散列冲突实际上是不可避免的。因此,大多数哈希表实现都有一些冲突解决策略来处理此类事件。 .NET 的 Hashtable 实现似乎使用了double hashing

3) 只要您提供正确的哈希码,您就不必担心这一点。如果有兴趣,请阅读有关哈希表的 wiki 文章,其中解释了几种技术。

更新: 在碰撞处理中Hashtable和Dictionaries的实现中有a difference。显然 Hashtable 已过时,首选 DictionaryHashSet

正如 Jim Mischel 所提到的,您应该重写 GetHashCode 以及 Equals。无法插入相等的项目,但具有相同哈希码的项目由您选择的集合类型处理。

【讨论】:

  • 非常感谢您的回答。实际上,如果我将 GetHashCode() 建立在从数据库检索到的主键字段上,我不会将冲突的变化归零吗?但是,如果哈希毕竟可以被复制,那么.NET 是否会在发生冲突时自动处理重新哈希/双重哈希值?在采访中,听起来好像我有责任自己做点什么。 :) 也许他们只是想听听内部使用的双重哈希,我没有说。
  • 如果 DB pk 类型是 int 并且字典只包含该类型的对象而不是 yes。 (您只需在 GetHashCode 函数中返回 pk 字段)。但大多数时候你需要一个好的散列函数,见stackoverflow.com/questions/263400/…
  • 我同意@Magnus。至于处理冲突,这只是需要注意的事情,因此您会理解为什么尽可能唯一的哈希函数很重要。
  • @Magnus:但是,如果数据库主键与哈希表槽之间存在一对一映射,那么这只会将冲突的可能性降低到零。如果键空间大于哈希表的大小,就会发生冲突。
  • 当实际加载因子达到 Dictionary 指定的加载因子时,Dictionary 中的桶数自动增加到大于当前 Dictionary 桶数两倍的最小素数。使用数据库中的 pk(即 int)将产生最佳散列函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2010-09-15
相关资源
最近更新 更多