完美的哈希函数是否保证没有冲突?

时间:2013-05-11 20:40:19

标签: c# hash hashtable perfect-hash

我一直在阅读和学习哈希和哈希表,并使用一些代码(我还是很新的,所以我可能说错了,我想念)。我找到了完美哈希函数的问题。只要我有自己的自定义类型,它以某种方式具有完美的哈希函数:

class Foo
{
    private int data;

    override int GetHashCode()
    {
        return data.GetHashCode();
    }
}

int的哈希码是int本身,所以我有一个完美的哈希函数,对吧?但是当我们使用散列函数通过简单的公式将对象映射到散列表时:

index = foo.GetHashCode() % hashtable.Length

我们得到一个变量索引,它取决于我们在哈希表中有多少元素。如果哈希表的大小只是int.MaxValue,那么我们将拥有一个完美的哈希函数。例如,假设我们有一个大小为2的哈希表。如果我们哈希例如数字1和3,我们得到

1 % 2 = 1
3 % 2 = 1

碰撞!我对哈希和哈希表有什么不妥吗?结果表明,完美的哈希函数并不完美。

3 个答案:

答案 0 :(得分:7)

直到现在,你还可以。

index = foo.GetHashCode() % hashtable.Length

你的哈希函数是完美的,但是当你计算模数时,你实际上是在使用不同的哈希函数。在这种情况下,您的哈希函数int.GetHashCode 是完美的,但使用foo.GetHashCode() % hashtable.Length 的数据结构不是。也就是说,有一件事是对象的哈希值,而另一件事就是持有这些对象的结构所使用的哈希值。

为了使您的数据结构更加完美,其最大大小也必须是整数。

那么我们为什么不在Dictionary发生碰撞?实际上,我们这样做。如果两个对象AB在字典中具有相同的哈希值,则会发生冲突。会发生什么是字典运行A.Equals(B)作为最终检查以查看这两个对象实际上是否相同。如果是,则会因为重复而获得例外。如果他们不这样做,他们都被保存在相同的字典哈希下。

答案 1 :(得分:3)

  1. 是的! (如上所述,按照定义)

  2. 你从哪里获得p.h.f? 您想要散列固定的,即不同的(即没有多个集合)值的常量集合S. 到组1 .. | S |,双射。 显然,p.h.f取决于集合S.

  3. 此外,从S中删除一个元素,并添加另一个元素,几乎肯定会发生碰撞(新元素与旧元素的碰撞)。

  4. 所以,你实际上想要“一个p.h.f.用于这样一个很好定义/描述的集合”。 然后我们可以尝试找到一个。

答案 2 :(得分:2)

是的,保证完美的哈希函数不会发生冲突。

这是它的定义!

来自维基百科(http://en.wikipedia.org/wiki/Perfect_hash_function

  

集合S的完美散列函数是一个散列函数,它将S中的不同元素映射到一组整数,没有碰撞。完美的哈希函数具有许多与其他哈希函数相同的应用程序,但具有不必实现冲突解决的优点