单独链接的负载系数?

时间:2018-03-04 12:10:39

标签: hash hashtable hash-function load-factor

为什么建议在单独链接中加载因子为1?

我见过很多人说这是推荐的,但没有给出明确解释为什么

在Open寻址中,我知道负载因子应该介于0.5和0.7之间,因为在处理冲突时找到未占用的索引应该是一个快速的操作。但我不明白为什么在Separate Chaining中加载因子为1应该更好。我的意思是,如果我有一个大小为100的表,是不是仍然有可能所有100个元素哈希到同一个索引并放在同一个列表中?上帝,我真的无法理解为什么分离链的特定负载因子应为1。

1 个答案:

答案 0 :(得分:5)

tl; dr:为了节省内存空间而使占用插槽不占用,并且通过最小化列表遍历操作的数量来加快访问速度。

如果您将负载系数理解为n_used_slots / n_total_slots

具有 load factor 1 的情况恰好描述了使用单独链接冲突处理的,实现良好的哈希表的理想情况:没有插槽留空。

另一种经典方法,即“打开地址”,要求表在添加新项目时始终具有可用的空闲插槽。调整表的大小对于每个项目来说都太昂贵了,但是我们也受到内存的限制,并且不想有太多未使用的插槽。必须在速度(很少调整表大小,快速插入和查找)和内存(很少有空插槽)之间找到平衡(在编程中如此频繁)。 理想负载因子基于这种平衡思想,可以根据实际的哈希函数,值域和其他因素进行估算。

另一方面,使用独立链接,我们通常期望从一开始就拥有(方式)比可用哈希表槽更多的项目。如果发生冲突,我们需要将该项目添加到存储在特定插槽中的链表中。由于在链接列表中进行搜索的成本很高,因此我们希望最大程度地减少列表遍历操作。为此,最好的情况是让 all 插槽充满理想长度的列表!填充所有插槽对应的负载系数为1。

换句话说,负载因子<1表示有空插槽,必须将项目添加到另一个插槽中的链表中,这会增加列表遍历操作的数量并浪费一些内存。

关于尺寸为100的表的示例:是的,所有项目可能会碰撞并仅占据一个插槽。在这种情况下,有效负载系数将为0.01,并且性能会受到严重影响。

如果您将负载系数理解为n_items / n_total_slots

在这种情况下,加载系数可以大于1。系数<1表示您有空插槽,而系数> 1意味着有多个插槽容纳多个项目,因此需要遍历列表。在第一种情况下,您浪费空间,而在第二种情况下,遍历列表会导致(小的)性能下降,具体取决于列表的大小。

示例:负载系数为10表示平均 每个插槽可容纳10个项目。因此,搜索项目意味着平均遍历5个列表节点

1的加载因子意味着您不浪费空间并且具有最快的查找速度,如果您使用了不错的哈希函数来确保规则且均匀地使用插槽。