发布时间:2025-03-16 15:14:34 点击量:
HASH GAME - Online Skill Game GET 300
每个新插入的条目都被附加到分配给插槽的动态数组的末尾。动态数组以精确匹配的方式调整大小,这意味着它只根据需要来增加字节的多少。人们发现,有些替代技术诸如通过块的大小或页面来增加数组可以提高插入性能,但需要更多的空间。这种变化更有效地利用了中央处理器缓存和转换后备缓冲器(TLB),因为插槽条目是按照顺序存储在内存中的。它还省去了链表所需的下一个指针,从而节省了空间。尽管频繁调整数组大小,但发现操作系统由此而产生的空间开销(如内存碎片)很小。
在另一种称为开放寻址的策略中另一个冲突解决策略是开放定址法,该方法将所有条目记录都存储在自身的桶单元数组中。当必须插入新条目时,将检查存储桶,从散列到插槽开始,并按一定的探测顺序进行,直到找到未占用的插槽位。当搜索条目时,以相同的顺序扫描存储桶,直至找到目标记录,或者找到未使用的槽位数组,这表明哈希表中没有这样的关键码。[17]定名为“开放寻址法”是指明了一个事实,项目的位置(“地址”)不是由其哈希值决定的。这种方法也称为封闭散列法;它不应该与通常意味着分离链接法的“开放散列”或“封闭寻址”混淆。
另一方面,当需要存储的条目数量很大时,普通的开放寻址是一个糟糕的选择,因为这些条目会填满整个CPU高速缓存行(抵消了高速缓存的优势),出现了大量的空槽位,因而浪费了大量的存储空间。如果开放寻址表只存储对元素的引用(外部存储),即使是处理大量的条目记录,它也会使用与链接相当的空间,但会失去速度优势。一般来说,开放寻址更适用于那些具有较少条目记录的哈希表,这些较少的条目记录可以存储在哈希表中(内部存储)并适合缓存行。它们特别适合处理只有一个单词或更少的条目记录。如果希望哈希表具有高装填因子,需要处理的记录也很大,或者数据大小可变,那么使用链式哈希表的性能通常也一样或更好。
另一种开放寻址解决方案是布谷鸟散列法,它确保在最坏的情况下查找时间不变,插入和删除的摊销时间不变。它使用两个或多个散列函数,这意味着任何键/值对都可以位于两个或多个位置。执行查找时,使用第一个散列函数,如果找不到键/值,则使用第二个散列函数,依此类推。如果在插入过程中发生冲突,则使用第二个散列函数对关键码进行重新散列,以将其映射到另一个桶。如果所有散列函数都已使用,但仍存在冲突,则它所冲突的关键码将被移出,为新的关键码腾出空间,旧关键码将用其他散列函数之一重新散列,从而将其映射到另一个桶。如果该位置也导致冲突,则重复该过程,直到没有冲突或该过程遍历所有存储桶,在此次过程中哈希表被调整大小。通过将多个散列函数与每个桶中的多个单元相结合,可以实现非常高的空间利用率。
跳房子哈希算法通过在原始哈希桶附近定义一个邻域来工作,在该邻域中总是可以找到给定的条目。因此,搜索限于该邻域中的条目数,在最坏的情况下这个邻域范围内的条目数量成对数关系分布,确保最坏平均查询时间为常数,并且邻域中的条目正确对齐通常需要一次高速缓存缺失。插入条目时,首先尝试将其添加到邻域范围内的桶中。然而,如果该邻域中的所有桶都被占用,则该算法将依次遍历所有桶单元,直到找到一个开放的槽位(未被占满的桶)(与线性探测一样)。此时,由于空桶在邻域区域之外,它们会以一系列跳跃重复移动。(这类似于布谷鸟散列法,但不同之处在于,在这种情况下,空槽被移动到邻近区域,而不是为了最终找到空槽而将项目移出。)每一跳都会使开放槽更靠近原始邻域,而不会使沿途任何桶的邻域属性无效。最后,开放的插槽位已经被移动到邻域范围内,正等着入的条目就可以被添加到其中。
双哈希冲突解决方案的一个有趣变化是罗宾汉哈希。[19][20]其设计思路是,如果一个新的关键码的探测次数大于当前位置的关键码的探测次数,它可能会替换已经插入的关键码。这样做的最终效果是减少了表格[21]中最坏情况的搜索时间。这类似于有序散列表,除了碰撞键的标准不依赖于键之间的直接关系。由于出现最坏的情况概率和探针数量的变化都显著减少,一个有趣的变化是哈希表探测可以从预期的成功探测值开始,然后从该位置向两个方向扩展。[22]外部罗宾汉散列法(External Robin Hood hashing)是这种算法的扩展,哈希表存储在一个外部文件中,每个表位置对应于一个固定大小的页面或者记录为B的桶单元。[23]
单调性关键码如果知道键值总是单调的增加(或减少),那么通过在每个哈希表调整大小操作中保持单个最近键值的列表,可以实现一致性哈希算法的变化。查找时,在这些列表条目定义的范围内的关键码被导引到适当的哈希函数,实际上是哈希表,对于每个范围,这两者都可能不同。由于将条目总数增加一倍是很常见的,所以只需要检查O(log(N))范围,重定向的二进制搜索时间为O(log(log(N))))。与一致性哈希算法一样,这种方法保证任何关键码的哈希一旦发布,将永远不会改变,即使哈希表后来增长了。