我一直在阅读和学习哈希和哈希表,并使用一些代码(我还是很新的,所以我可能说错了,我想念)。我找到了完美哈希函数的问题。只要我有自己的自定义类型,它以某种方式具有完美的哈希函数:
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
碰撞!我对哈希和哈希表有什么不妥吗?结果表明,完美的哈希函数并不完美。
答案 0 :(得分:7)
直到现在,你还可以。
index = foo.GetHashCode() % hashtable.Length
你的哈希函数是完美的,但是当你计算模数时,你实际上是在使用不同的哈希函数。在这种情况下,您的哈希函数int.GetHashCode
是完美的,但使用foo.GetHashCode() % hashtable.Length
的数据结构不是。也就是说,有一件事是对象的哈希值,而另一件事就是持有这些对象的结构所使用的哈希值。
为了使您的数据结构更加完美,其最大大小也必须是整数。
那么我们为什么不在Dictionary
发生碰撞?实际上,我们这样做。如果两个对象A
和B
在字典中具有相同的哈希值,则会发生冲突。会发生什么是字典运行A.Equals(B)
作为最终检查以查看这两个对象实际上是否相同。如果是,则会因为重复而获得例外。如果他们不这样做,他们都被保存在相同的字典哈希下。
答案 1 :(得分:3)
是的! (如上所述,按照定义)
你从哪里获得p.h.f? 您想要散列固定的,即不同的(即没有多个集合)值的常量集合S. 到组1 .. | S |,双射。 显然,p.h.f取决于集合S.
此外,从S中删除一个元素,并添加另一个元素,几乎肯定会发生碰撞(新元素与旧元素的碰撞)。
所以,你实际上想要“一个p.h.f.用于这样一个很好定义/描述的集合”。 然后我们可以尝试找到一个。
答案 2 :(得分:2)
是的,保证完美的哈希函数不会发生冲突。
这是它的定义!
来自维基百科(http://en.wikipedia.org/wiki/Perfect_hash_function)
集合S的完美散列函数是一个散列函数,它将S中的不同元素映射到一组整数,没有碰撞。完美的哈希函数具有许多与其他哈希函数相同的应用程序,但具有不必实现冲突解决的优点