【问题标题】:Double Hashing efficiency with word dictionary字典双哈希效率
【发布时间】:2015-04-20 22:01:10
【问题描述】:

简单地说,我有一个单词字典,我正在将它们添加到哈希表中。

我正在使用双散列(不是传统方法),以下是产生最佳结果的方法。

    public static int getHashKey(String word) {

        int index = 0;

        for(int i = 0; i<word.length(); i++){

            index += Math.pow(4,  i)*((int)word.charAt(i));
            index = index % size;
        }
        return index;
    }

    public static int getDoubleHashKey(String word) {

        int jump = 1;

        for(int i = 0; i<word.length(); i++){

            jump = jump * word.charAt(i);
            jump = jump % size;
        }
        return jump;

    }

这给了我 127,000 次碰撞。我还有一个 2 倍的素数哈希表大小,它无法更改。

有什么方法可以改进双散列算法? (以上两种方法之一)。

我知道这取决于我们在哈希表中存储的内容等。但是是否有任何直观的方法或一些更普遍适用的技巧,这样我就可以避免更多的冲突。

【问题讨论】:

  • 取第一个哈希为word.hashcode(),第二个哈希遍历你的实现
  • 什么是有效尺寸,而且,为什么不从大素数开始,而不是从 1 开始?
  • 感谢各位的回答。 @JigarJoshi 我目前正在尝试避免使用 Java API
  • @AmirAfghani 数组大小为 216555,但我限制为哈希表大小的两倍。将初始跳跃大小更改为更大的素数几乎没有什么区别,但我从来没有想过,所以谢谢!
  • 我没有什么可以备份的,但我认为你应该只计算一次jump % size,在循环之外。直观地说,如果您在每次迭代时计算模数,您更有可能找到相同的 jump 值,因为它们属于较小的空间。

标签: java dictionary hash double-hashing


【解决方案1】:

我在大约 336 531 个条目的字典上运行了一个小 Scala 程序。版本 2 (118 142) 的冲突明显少于版本 1 (305 431)。请注意,版本 2 接近最佳碰撞次数,因为 118 142 + 216 555 = 334 697,因此 334 697/336 531 = 0-216555 范围内使用的值的 99.46%。使用模outside循环确实改进您的哈希方法。

import scala.io.Source

object Hash extends App {
    val size = 216555
    def doubleHashKey1(word: String) = {
        var jump = 1;
        for (ch <- word) {
            jump = jump * ch;
            jump = jump % size;
        }
        jump
    }

    def doubleHashKey2(word: String) = {
        var jump = 1;
        for (ch <- word) jump = jump * ch;
        jump % size;
    }

    def countCollisions(words: Set[String], hashFun: String => Int) = words.size - words.map(hashFun).size
    def readDictionary(path: String) = Source.fromFile(path).getLines.toSet

    val dict = readDictionary("words.txt")
    println(countCollisions(dict,doubleHashKey1))
    println(countCollisions(dict,doubleHashKey2))
}

为了处理整数溢出,您必须使用不同的(但实现起来很简单)方法来计算模数以返回正值。另一项测试是查看碰撞是否静态分布良好。

【讨论】:

    猜你喜欢
    • 2011-06-10
    • 1970-01-01
    • 2019-06-01
    • 2021-02-13
    • 2016-08-12
    • 2013-03-21
    • 2012-08-23
    • 2014-01-04
    • 1970-01-01
    相关资源
    最近更新 更多