【问题标题】:Hashing a string for use in hash table (Double Hashing)散列用于散列表的字符串(双散列)
【发布时间】:2011-12-25 08:35:04
【问题描述】:

我正在尝试使用双散列将字符串键散列到散列表中。我做了类似的事情:

protected int getIndex(String key) {
  int itr = 0,
      size = this.values.length,
      index1,
      index2,
      index = 0;

  do {
    // do double hashing to get index for curr [itr] (iteration)
    index1 = Math.abs(key.hashCode()) % size;
    index2 = size - ((key + key + "#!@").hashCode() % size); # trying very hard to eliminate clash, but still fails ... TA and AT gets index 2 when size = 5
    index = (index1 + (itr * index2)) % size;

    // if itr > set threshold, exit
    itr++;
    if (itr > 200) {
      index = -1;
      break;
    }

    // once index found, exit loop
  } while (index > 0 && this.keys[index] != null && !this.keys[index].equals(key));

  return index;
}

主要部分是do 之后的第 3 行。我可以说如果我使用Double Hashing,它应该消除碰撞的可能性吗? size 是我的哈希表的唯一键的总可能值

【问题讨论】:

  • AFAIK 真的很难找到一种可以消除碰撞的算法。正如您所说,哈希表在发生冲突时使用重新散列/双重散列。但是当涉及到 Dictionary 时,它使用链接来避免冲突。现在,与重新散列/双重散列相比,链接中的查找时间将相对较少。简而言之,如果您能够实现一个没有冲突的算法,那就太好了。否则,我个人建议您使用链接(冲突解决)而不是重新散列。
  • 我不会修改 index1index2 的大小。当你丢弃大量信息时。您只需要 %size 最终值。特别是,index2 很有可能为 0。

标签: java hash hashtable double-hashing


【解决方案1】:

所以我看到这里发生了两件事

  1. 使用两种不同的哈希值并将它们组合起来,以获得更分散的哈希值
  2. 如果哈希失败,请尝试更远的新位置

乍一看,这两种方法似乎都是减少哈希冲突的好方法。然而,仔细观察,这两者都陷入了真正的算法问题。

组合两个哈希
散列算法被设计成在整数谱中分布得相当好。就像将两个随机数加在一起不会给您带来更多随机性一样,将两个哈希加在一起也不会让您获得更多分布。事实上,将两个相同分布加在一起总是会给你一些不均匀分布的东西。因此,任何一种使用相同底层算法的双重哈希策略都比单一哈希策略差。

尝试新地点
如果第一个发生冲突,尝试使用新哈希的算法很诱人。但是,这会导致算法的检索部分出现问题。当您将某些东西放入哈希中时,它会撞到另一个位置。然后,当您去检索该值时,它不存在。更糟糕的是,您是否找到它取决于第一个元素是否仍然存在。如果它已被删除,则无法判断您要查找的项目是否在更远的位置,或者它是否不存在。最终,.contains 测试必须经过所有 200 次迭代才能确定它正在寻找的哈希不存在。

最好的解决方案是使用 Java 提供的开箱即用的散列。如果您遇到很多冲突,最好在哈希中使用较低的负载因子。这会增加存储桶的数量,并降低发生冲突的可能性。

【讨论】:

    猜你喜欢
    • 2020-03-17
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    相关资源
    最近更新 更多