My Hash Table实现具有在负载达到约70%时调整表大小的功能。我的哈希表是通过单独的冲突链接实现的。
我是否应该在任何时候调整哈希表的大小,或者我应该像它一样离开它?否则,如果我增加了大小(几乎是两倍,实际上我遵循这个:http://planetmath.org/encyclopedia/GoodHashTablePrimes.html)当负载为70%时,我应该在负载达到30%或更低时将其调整大小吗?
答案 0 :(得分:3)
如果您具有高质量的哈希函数,则哈希表不必具有素数长度(请参阅here)。你可以使它们的权力为2,这大大加快了索引的计算速度。
为什么这与问题相关?因为当你缩小二次幂哈希表时,你可以将所有条目保留在它们所在的下半部分,并简单地将链接列表添加到插槽i
中(从上半部分)到插槽中的链接列表{ {1}}。
答案 1 :(得分:2)
如果记忆力便宜,请不要管它。如果内存很昂贵,请按照您的建议调整hysterisis。完成后,对结果进行分析,以确保其表现良好并且没有做任何愚蠢的事情。
答案 2 :(得分:1)
您是否正在编写用于通用目的的哈希表,或者它是否有特定目的?我建议不要为一般实现调整较小的大小。这将使您的表格保持简单,并在经常填充和清空表格的情况下防止内存抖动。如果最终遇到哈希表需要缩小的情况,请在该时间点扩展它。
答案 3 :(得分:0)
第一个想法:生成哈希表的唯一原因是因为如果冲突太多,哈希表性能会下降。当表的负载超过70%时使表增长是防止发生这种情况的一个很好的经验法则,但这只是一个经验法则。更好的方法是跟踪冲突的数量,并且仅在哈希表超过特定限制或达到特定碰撞率后才增长哈希表。毕竟,您为什么要增长一个哈希表,该哈希表加载了90%的数据,却没有发生一次冲突?这样就没有优势了。
第二个想法:缩小哈希表的唯一原因是节省内存,但缩小哈希表可能会增加冲突次数,从而降低查找性能。这是经典的速度与内存的权衡,为什么要自己解决呢?交给使用您的代码的人。只是永远不要自己收缩,而是提供收缩方法。如果需要较低的内存使用量,则使用您代码的任何人都可以定期调用收缩。如果需要最大性能,那么使用您的代码的任何人都不应调用缩减。其他所有人都可以使用某种启发式方法来决定是否以及何时调用缩小。
第三个想法:增长或收缩时,请始终以保证操作后一定的负载系数的方式增长/收缩。例如。当增长时,请始终增长以使之后的负载率为50%;当收缩时,请始终以收缩后的负载率为70%的方式进行收缩。当然,这并没有说明冲突的数量,因此在增长/收缩之后立即添加元素可能会导致哈希表再次增长,但这是不可避免的,因为模拟增长/收缩的效果通常过于昂贵。而且,一旦没有进一步的修改计划,通常会调用收缩命令,因此它应该节省内存,而不是避免将来再次增长。
最后一个想法:对于您做出的每个决定,对于某些用例,您将使哈希表变得更好,而对于其他一些用例,则使哈希表变得更糟。如果您知道将如何使用哈希表,那么这将不是问题。但是,如果您不这样做,并且通常不这样做,为什么还要自己做出这些决定?只是委派他们。允许您的代码用户自定义所有小细节,例如通过允许在创建哈希表时设置所有这些因素,或者通过允许哈希表具有委托函数(当不确定该怎么做时可以随时询问的回调函数)来增大或缩小多少。这样,您的代码的每个用户都可以在运行时为他们自定义代码,无论他们需要哪种使用场景。