字频哈希表

时间:2015-10-08 23:21:11

标签: java hash

好的,我有一个项目要求我有一个动态哈希表来计算文件中单词的频率。我必须使用java,但是,除标准数组外,我们不允许使用任何内置数据类型或内置类。此外,我不允许在互联网上使用任何已知速度快的哈希函数。我必须自己创建哈希函数。最后,我的导师还希望我的桌子从尺寸开始#1;#"每次添加新密钥时,大小加倍。

我的第一个想法是将构成单词的字母的ASCII值相加并使用它来制作散列函数,但具有相同字母的不同单词将等于相同的值。

我该如何开始? ASCII想法是否正确?

2 个答案:

答案 0 :(得分:1)

哈希表通常不会一般一个值和一个哈希之间的一对一映射。哈希表预计会发生冲突。也就是说,期望散列函数的域大于范围(即,散列值)。但是,一般的想法是你提出了一个哈希函数,其中碰撞的概率非常小。如果您的哈希函数是统一的,即,如果您将其设计为使得每个可能的哈希值具有相同的生成概率,那么您可以通过这种方式最小化冲突。

发生碰撞并不是世界末日。这只意味着您必须搜索该哈希值的列表。如果您的散列函数很好,那么整体查找性能仍应为O(1)。

生成散列函数是它自己的主题,没有一个答案。但是你开始的一个好地方可能是使用字符串中字符的按位表示,并对它们执行某种卷积操作(旋转,移位,XOR)。您可以基于某些初始种子值以某种方式执行这些操作,然后使用散列的第一步输出作为下一步的种子。通过这种方式,您最终可以放大卷积的效果。

例如,假设您获得了字符A,其中十六进制为41,二进制为0100 0001。您可以将每个位指定为某个操作(当0为0时,位0为ROR,1为时为ROL; 0为0时为0,如果为1则为XOR等) 。您甚至可以根据值本身来决定要进行多少卷积。例如,您可以说较低的半字节指定您将进行多少右旋转,而较高的半字节指定您将进行多少左旋转。然后,一旦得到最终值,您将使用它作为下一个字符的种子。这些只是一些想法。用你的想象力来看看你得到了什么!

答案 1 :(得分:0)

你的哈希函数有多好并不重要,你总会遇到需要解决的冲突。

如果你想通过使用ASCII值来保持你的方法,你不应该只添加值,这将导致很多冲突。您应该使用值的功能,例如“帮助”这个词就像:'H'* 256 +'e'* 256 +'l'*256²+'p'*256³。或者在伪代码中:

int hash(String word, int hashSize)
    int res = 0
    int count = 0;
    for char c in word
        res += 'c' * 256^count
        count++
        count = count mod 5
    return res mod hashSize

现在你只需编写自己的Hashtable:

class WordCounterMap
    Entry[] entrys = new Entry[1]

    void add(String s)
        int hash = hash(s, entrys.length)
        if(entrys[hash] == null{
            Entry[] temp = new Entry[entry.length * 2]
            for(Entry e : entrys){
                if(e != null)
                    int hash = hash(e.word, temp.length)
                    temp[hash] = e;
            entrys = temp;
            hash = hash(s, entrys.length)
        while(true)
            if(entrys[hash] != null)
                if(entrys[hash].word.equals(s))
                    entrys[hash].count++
                    break
            else
                entrys[hash] = new Entry(s)
            hash++
            hash = hash mod entrys.length

    int getCount(String s)
        int hash = hash(s, length)
        if(entrys[hash] == null)
            return 0
        while(true)
             if(entrys[hash].word.equals(s))
                 entrys[hash].count++
                 break
             hash++
             hash = hash mod entrys.length


class Entry
    int count
    String word

    Entry(String s)
        this.word = s
        count = 1