C 哈希表的大小

C 哈希表的大小,c,hash,hashtable,C,Hash,Hashtable,让哈希表的大小为静态,我设置了一次。我想根据条目的数量进行设置。搜索得到的大小应该是一个素数,等于2*N我猜是最接近的素数,其中N是条目数 为简单起见,假设哈希表不会接受任何新条目,也不会删除任何新条目 参赛作品的数目分别为200、2000、20000和2000000 但是,将大小设置为2*N对我来说似乎太多了。不是吗?为什么?如果是,我应该选择哪个尺码 我知道我们希望避免碰撞。我也知道,也许哈希表没有理想的大小,但我正在寻找一个起点 我使用C语言,我想建立自己的结构来教育自己。你的问题的答案在

让哈希表的大小为静态,我设置了一次。我想根据条目的数量进行设置。搜索得到的大小应该是一个素数,等于2*N我猜是最接近的素数,其中N是条目数

为简单起见,假设哈希表不会接受任何新条目,也不会删除任何新条目

参赛作品的数目分别为200、2000、20000和2000000

但是,将大小设置为2*N对我来说似乎太多了。不是吗?为什么?如果是,我应该选择哪个尺码

我知道我们希望避免碰撞。我也知道,也许哈希表没有理想的大小,但我正在寻找一个起点


我使用C语言,我想建立自己的结构来教育自己。

你的问题的答案在某种程度上取决于你的哈希函数的质量。如果您有一个高质量的散列函数,即平均值为的散列函数,则:

有一个素数桶的必要性消失了; 您可以预期每个bucket的项目数为。 因此,首先,使用素数bucket的建议本质上是一个难题,有助于缓解哈希函数不好的情况。如果您有一个高质量的散列函数,那么就不清楚桶的数量本身是否有任何限制,一个常见的选择是使用2的幂,这样模就只是一个按位的,尽管这两种方式都不重要。一个好的哈希表实现将包括一个二级哈希,以尝试缓解原始哈希函数质量差的情况——请参阅Java哈希表的源代码以获取示例

常见的负载系数为0.75,即每75个条目有100个铲斗。这意味着大约50%的存储桶中只有一个入口,因此性能很好,当然也会浪费一些空间。正确的负载系数取决于您想要进行的时间/空间权衡

在高性能应用程序中,潜在的设计考虑因素还包括如何实际组织内存中的结构/存储桶,以最大限度地提高CPU缓存性能。最佳结构的答案本质上是在数据实验中表现最好的结构

大小应该是一个素数,等于2*N我猜最近的素数,其中N是条目数

当然不应该。这个建议可能意味着负载系数0.5是一个很好的折衷方案,至少在默认情况下是这样

大小的首要性取决于你的选择。有些算法需要素数表大小的双散列、二次散列,而其他算法则不需要,而且它们可以从表大小的2次方获益,因为它允许非常便宜的模运算。然而,当最接近的可用表大小相差2倍时,哈希表的内存使用可能不可靠。因此,即使使用线性散列或单独链接,也可以选择大小为2的非幂。在这种情况下,选择特殊的素数大小是值得的,因为:

如果选择基本表大小是因为算法需要这样做,或者是因为您不满意2次方大小所隐含的内存使用不可靠性,那么表槽计算按表大小进行模化可以与哈希相结合。更多信息,请参阅

从Neil Coffey的答案来看,当散列函数分布不好时,表大小为2的幂是不可取的,这一点是不切实际的,因为即使你的散列函数不好,它仍然使用2的幂比切换到素数表大小更快,因为单积分除法在现代CPU上的速度仍然较慢,这就需要好的雪崩函数所要求的多种多重运算和移位运算。G从第3页开始

参赛作品将有200、2000、20000和2000000份

我不明白你这是什么意思

但是,将大小设置为2*N对我来说似乎太多了。不是吗?为什么?如果是,我应该选择哪个尺码

一般规则是:为哈希表分配的内存越多,哈希表的运行速度就越快。你可以找到一些图表来说明这一点。所以,如果您认为分配表大小~2*N会浪费内存,您可以自由选择较小的大小,但要准备好,哈希表上的操作平均会变慢

我知道我们希望避免碰撞。我也知道,也许哈希表没有理想的大小,但我正在寻找一个起点


要完全避免碰撞是不可能的记得吗一定比例的碰撞是一种常见情况。此比率仅影响平均操作速度,请参见上一节。

我不知道最佳大小,但请记住,您将遇到哈希冲突。我怀疑理想的桶数是多少
s与哈希空间的大小有关,因此与哈希冲突的概率有关。如果N较大,则2*N似乎过度使用了内存。如果N很小,哈希冲突将非常罕见,因此2*N似乎也是浪费。@EricJ。我更新了我的问题。为了教育自己-然后用一系列大小进行实验,并绘制每秒的后续操作,以了解折衷。当然。。。对于双负载,系数=0.5;装载系数我将使用每个桶的列表来避免碰撞,这是毫无疑问的。我喜欢你的方法。我还没有决定我的哈希函数是哪一个。我认为第一个链接可以帮助我做出决定。我部分理解你的回答。例如,如果我们有一个完美的哈希函数,那么哈希表的大小应该是N,每个bucket一个项目。泊松分布与如何插入项有关?我的意思是,这与物品被放入某个桶中的可能性有关?至于载荷系数,我是否也要把它放在等式中?如果你是我,你会如何设置桌子的大小?我现在对使用一个100元表不感兴趣。不,一个完美的哈希函数是一个有效地允许我们考虑100个随机数来代表随机选择的条目的函数。因此,假设你有100个桶,你挑选了100个范围在1-100之间的随机数,也就是说,一个思维实验相当于拥有与物品相同数量的桶。事实上,在挑选了100个随机数之后,你不会期望每个数都只出现一次;相反,有些数字根本不会出现,有些数字会重复2到3次……因此,让每个水桶只装满一次而不浪费的理想对于处理一般情况来说根本不是一个现实的目标。这与哈希函数不完美无关;相当地从统计学上讲,如果你想避免在任何给定的存储桶中有很多项,那么使用完美散列函数的情况实际上是有一些浪费。实际上,你可以尝试的一个很好的编程练习是我提到的随机数模拟:编写一个程序,该程序接受范围为1-1000的1000个随机数并计数每个数字出现多少次,从而查看铲斗长度的分布。然后以1-500范围内的1000个数字重复,模拟500个桶中的1000个项目,并查看分布情况。然后1000个在1-2000范围内的数字,我可以做到。因此,我应该首先找到一个好的哈希函数,然后再考虑哈希表的大小。当发生冲突时,我会在bucket中简单地创建一个列表,并通过蛮力搜索它。参赛作品将是2002000。。。意味着条目的数量将为200条等。。我理解这种权衡。但是,作为另一个答案,您也不建议我的哈希表的大小。这是因为我应该首先选择散列函数吗?@G.Samaras默认情况下,实际上第一个选择的大小应该是2的幂,最接近2*N。只有在您确实需要更好地控制内存使用时,才使用基本大小。在带有性能图的链接文章中有一个有趣的旁注。一旦为哈希表分配的内存大于CPU缓存,增加内存大小就没有好处,因为算法增益往往会被CPU缓存未命中抵消。