我最近在几次关于Hashtables的采访中进行了深入研究,并且何时需要覆盖GetHashCode()。讨论一直在深入和深入,直到我全身心投入。
我现在正做一些研究,以涵盖下次准备好的一切。
我找到了这篇我想分享的优秀文章: http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx#datastructures20_2_topic5
1)我觉得不太满意的是字典是基于哈希的事实,但列表显然不是。这仅仅意味着在List<>中进行搜索和Array []是线性的,而在字典或散列表中搜索是不变的,因此更快?这就是全部吗?
2)如果我使用类作为字典中的键,我需要根据任何必需的标识字段覆盖该类的GetHashcode()以使实例唯一。但是,仍然可能发生两个ID字段相等并且将生成相同的哈希码?如果这是两个实例与相同哈希码冲突期间发生的情况?
3)如何解决碰撞?我在文章中读到了关于Hashtable和Chaining for the Dictionary的碰撞情况下的rehashing方法。但我仍然不确定它是如何工作的,因为我不是数学天才。 : - \有人可以更好地解释它是如何工作的吗?
非常感谢, 卡瓦
答案 0 :(得分:4)
1)通常,是的,Dictionary<T>
或HashSet<T>
具有恒定的时间访问权限。在未排序的List<T>
或数组中定位项目必须线性完成。通过排序集合,您可以进行二进制搜索,从而获得O(log n)访问时间。
2)如果在.NET中覆盖GetHashCode
,则还应覆盖Equals
方法。在.NET Dictionary
和HashSet
中,您无法插入相同的项目。在一般情况下,哈希冲突是不可避免的(除非您已经计算出完美的哈希值)。有几种方法可以解决冲突。
3)有关冲突解决的更多信息,请参阅http://en.wikipedia.org/wiki/Hash_table。
答案 1 :(得分:1)
哈希表是一种数据结构。可以找到更多信息when looking for more general information。
1)列表中的默认搜索是线性的(需要遍历所有元素)。完美的散列(无冲突)允许在最坏的情况下进行恒定的时间查找。更多的碰撞会导致查找速度变慢。
2)当散列大量可能键的随机子集时,哈希冲突几乎是不可避免的。因此,大多数哈希表实现都有一些冲突解决策略来处理此类事件。 .NET的Hashtable实现似乎使用double hashing。
3)只要您提供正确的哈希码,这是您不必担心的事情。如有兴趣,请阅读有关哈希表的维基文章,其中介绍了几种技术。
更新: 碰撞处理中Hashtable和Dictionaries的实现有a difference。显然,Hashtable已过时,首选Dictionary或HashSet。
正如Jim Mischel所提到的,你应该覆盖GetHashCode以及Equals。插入相同的项目是不可能的,但具有相同哈希码的项目将由您选择的集合类型处理。