Optimization 有多少个散列桶

Optimization 有多少个散列桶,optimization,hashtable,Optimization,Hashtable,如果我注意到一个散列表(或在散列表上构建的任何其他数据结构)正在填充,那么应该在什么时候构建一个包含更多bucket的新表。考虑到目前为止表中有n个项目,您如何计算出在新项目中要使用多少个桶 假设我有100个桶。当里面有50个项目时,我应该重新组织它吗?500? 5000? 或者我应该寻找最满的桶和钥匙吗?那么,当我到达这个点时,新的哈希表有多大 与此相关的是,如果您事先知道大约有多少项将进入,是否有方法计算桶的数量以获得良好的平均性能 我知道真正的答案取决于很多其他的考虑因素,比如在一个具体的

如果我注意到一个散列表(或在散列表上构建的任何其他数据结构)正在填充,那么应该在什么时候构建一个包含更多bucket的新表。考虑到目前为止表中有n个项目,您如何计算出在新项目中要使用多少个桶

假设我有100个桶。当里面有50个项目时,我应该重新组织它吗?500? 5000? 或者我应该寻找最满的桶和钥匙吗?那么,当我到达这个点时,新的哈希表有多大

与此相关的是,如果您事先知道大约有多少项将进入,是否有方法计算桶的数量以获得良好的平均性能

我知道真正的答案取决于很多其他的考虑因素,比如在一个具体的例子中,速度与大小的关系有多重要,但我在寻找一般的准则


我也知道我不应该优化这类事情,除非良好的分析表明这是一个瓶颈。我正在考虑一个会使用大量哈希表的项目,并想知道如何实现这一点。

通常,您会注意负载因子(非正式地,您已经说过),它的正式定义为α=n/n,即使用的桶与总桶的比率。为了使哈希表能够正常工作(或者至少从数学角度对其性能进行推理),最好的经验法则是,如果哈希表的填充率达到80%,则重新进行哈希运算(并不总是理想的,好吧,只是经验法则)。这意味着,如果你有100个桶和80件物品在里面,不管你之前发生过多少次碰撞,现在是时候增加容量了

你应该增加多少?嗯,也没有完美的价值。最简单的解决方案是每增加一次容量就增加一倍。所以它变成了200,400,800,等等。如果您认为这太多(毕竟,当哈希表变得非常大时,它将从8MB内存跳到16MB,并且您可能永远不会填满16MB),请选择较小的增长因子。我想至少推荐1/3(从100增长到133),也许让它每次增长50%作为折衷方案

请注意,所有这些还取决于如何处理碰撞。处理它们的一种简单方法(我个人最喜欢的方法)是在发生冲突时将项目存储在链接列表中。如果在同一个键上放置了3个项目,则最多只能进行3次比较才能找到它。由于链表对搜索非常无效,您可能希望提前增加容量,例如,如果使用60%的容量来保持哈希表的速度。OTOH,你可以做一些更复杂的事情,保持碰撞次数的统计数据。只要您几乎没有任何冲突(如果您有一个非常好的哈希函数),就根本不需要重新哈希,即使99%的容量正在使用。此外,如果您以复杂的方式处理冲突(例如,每个节点都是一个排序表,您可以在这些节点中执行二进制搜索),那么如果将该表加载到200%(因此您的项目数是容量的两倍),您的查找速度可能仍然足够快。在这种情况下,你可以统计最大的排序表有多大,当它大于8个条目时,你会认为这太慢了,然后你重新散列


重新散列非常缓慢,因此应尽可能避免。因此,如果您需要重新散列,不要只增加太少的容量,否则在添加更多项目时,您必须很快重新散列。因此,当您需要重新散列时,请使容量大大大于表中当前的项目数,否则所有内容的容量都太小。

取决于您正在构建的散列表的类型。如果使用的是基于固定数组的哈希表(与存储桶的链表相反),则应在表已满或达到最大探测计数时调整数组大小(取决于您是否更关心速度或内存)。如果您使用的是链表,那么内存就没有那么大的问题了,因为您不必搜索空的空间,所以调整大小也没什么大不了的


哈希表的关键是哈希算法,而不是存储桶的数量。理想情况下,每个bucket中最多需要一个项,因此理想情况下,当哈希表中的项数=bucket数时,应该调整大小。如果数据分布不均匀,则最好使用更好的哈希算法,而不是更好的调整大小策略。

哈希表通常有两种类型:打开和关闭

在一个打开的哈希表中,您可以根据哈希找到正确的bucket,然后构建挂起该bucket的项列表

在一个封闭的哈希表中,您可以使用哈希值找到初始bucket,如果它被占用,您可以探测下一个值。在最简单的情况下,您可以通过查找下一个空闲bucket来实现这一点,或者您可以从您的项中创建第二个哈希值并逐步执行(尽管您必须确保这是哈希表大小的素数模,以便访问所有bucket)

打开的哈希表通常不会调整大小。您将初始大小设置为您认为对问题合理的大小。正如其他人指出的,您可以在一个开放的哈希表上调整大小,但是现在很难对这个数据结构的性能进行推理。如果在给定bucket的长度为L时调整大小,则可能会在整个哈希表中只调整L个项目的大小,这是非常低效的

当加载因子(哈希表中的项数/存储桶数)达到某个预定义值时,关闭的哈希表将调整大小。我倾向于使用80%,但确切值不太可能太关键


封闭哈希表的好处是插入项的摊销成本始终为O(1)(假设哈希函数良好)。由于调整大小的成本,插入特定项可能是O(N),但这种情况很少发生。

如果使用线性哈希,表本身会自动执行