何时调整哈希表的大小?

时间:2011-02-10 16:01:37

标签: algorithm hashtable

在各种哈希表实现中,我看到了一个可变哈希表应该调整大小(增长)的“神奇数字”。通常,此数字介于每个已分配插槽的值的65%到80%之间。我假设权衡的是,更高的数字将带来更多冲突的可能性和更少的数量,而不是以使用更多内存为代价。

我的问题是这个号码是如何到达的?

这是武断的吗?基于测试?基于其他一些逻辑?

5 个答案:

答案 0 :(得分:6)

我认为你不想考虑表的“有多满”(总桶中有多少“桶”有值),而是为新物品找到一个点可能需要的冲突次数。

我读了几年前的一些编译器书(不记得标题或作者),建议只使用链接列表,直到你有超过10到12个项目。这似乎支持超过10次碰撞意味着需要时间重新调整大小。

The Design and Implementation of Dynamic. Hashing for Sets and Tables in Icon表明平均哈希链长度为5(在该算法中,平均冲突数)足以触发重新哈希。似乎测试支持,但我不确定我是否正确阅读了论文。

看起来调整大小的条件主要是测试的结果。

答案 1 :(得分:5)

据猜测,大多数人至少从书中的数字开始(例如,Knuth,第3卷),这是通过测试产生的。根据具体情况,有些人可能会在事后进行测试,并做出相应的调整 - 但从我看到的情况来看,这些可能属于少数。

正如我在previous answer中所概述的那样,“正确”数字也在很大程度上取决于您如何解决冲突。无论好坏,这个事实似乎被广泛忽视 - 人们经常不会选择特别适合他们使用的碰撞解决方案的数字。

OTOH,我在测试中发现的另一点是它很少会产生很大的不同。您可以在相当宽的范围内选择数字,并获得非常相似的整体速度。最重要的是要小心避免将数字推得太高,特别是如果你使用线性探测等方法进行碰撞解决。

答案 2 :(得分:2)

这取决于钥匙。如果你知道你的哈希函数对于所有可能的键都是完美的(例如,使用gperf),那么你知道你只有很少的冲突,所以数字更高。

但是大多数时候,你对键不太了解,除了它们是文本。在这种情况下,您必须猜测,因为您甚至没有测试数据来预先弄清楚您的哈希函数的行为。

所以你希望最好的。如果你的哈希函数对于密钥非常糟糕,那么你将会遇到很多冲突,并且永远不会达到增长点。在这种情况下,所选择的数字是无关紧要的。

如果您的哈希函数足够,那么它应该只创建一些冲突(少于50%),因此65%到80%之间的数字似乎是合理的。

那说:除非你的哈希表必须是完美的(=巨大的或大量的访问),不要打扰。如果你有十个元素,考虑到这些问题是浪费时间。

答案 3 :(得分:1)

据我所知,这个数字是基于经验测试的启发式算法。

哈希值的分布相当合理,似乎神奇的负载因子 - 如你所说 - 通常在70%左右。较小的负载系数意味着您浪费空间而没有真正的好处;更高的负载系数意味着您将使用更少的空间,但花费更多的时间来处理哈希冲突。

(当然,如果你知道你的哈希值是完美分布的,那么你的加载因子可以是100%,你仍然没有浪费的空间和没有哈希冲突。)

答案 4 :(得分:1)

冲突高度依赖于数据和使用的哈希函数。

大多数数字基于启发式或假设哈希值的正态分布。 (AFAIK值大约70%是可扩展哈希表的典型值,但是总是可以构造这样的数据流,您可以获得更多/更少的冲突)