完美的哈希建筑

时间:2012-06-01 11:45:15

标签: algorithm hash

为什么我们不使用SHA-1,md5Sum和其他标准加密哈希进行散列。它们足够智能以避免碰撞并且也不可恢复。因此,而不是提出一组可能有冲突的新哈希函数,为什么我们不使用它们。 只有我能够思考的原因是他们需要说大键说32bit。但仍然避免碰撞所以查找肯定会是O(1)。

2 个答案:

答案 0 :(得分:6)

  1. 因为它们很慢,原因有两个:
    1. 他们的目标是通过密码学方式保护,而不仅仅是防碰撞
    2. 它们产生的哈希值比哈希表中实际需要的哈希值大得多。
  2. 因为它们处理非结构化数据(八位字节/字节流),但是您需要散列的对象通常是结构化的,并且首先需要线性化

答案 1 :(得分:0)

  

为什么我们不使用SHA-1,md5Sum和其他标准加密哈希进行散列。他们足够聪明,可以避免碰撞......

错误原因是:

  • 两个输入cam仍然碰巧具有相同的哈希值。假设哈希值是32位,一个很好的通用哈希例程(即不利用实际键集合的洞察力)仍然至少有1/2 / 32的机会为任何2返回相同的哈希值键,然后2/2 ^ 32碰撞其中一个作为第三个键的机会被散列,3/2 ^ 32为第四个等等。
  • 具有不同的哈希值与将哈希值映射到哈希表中的不同哈希桶非常不同。散列值通常被修改为表大小以选择存储桶,因此最好 - 并且再次用于通用散列 - 在向散列表添加元素时发生冲突的可能性是#preexisting-elements / table-size。 / LI>
  

所以不要再提出一组新的哈希函数,它可能会发生冲突,为什么我们不使用它们。

因为速度通常是程序员在选择使用哈希表而不是二叉树时的目标。如果哈希值在数学上很难计算,它们可能比使用略多(但仍然不是特别)易于碰撞但计算速度更快的哈希函数花费更长的时间。也就是说,有时候对散列的更多努力可以得到回报 - 例如,当磁盘上存在哈希表时,以及寻求和获取的I / O成本。阅读记录使得哈希计算工作相形见绌。

antti对数据提出了一个有趣的观点......通用哈希例程通常用于具有特定起始地址和多个字节的二进制数据块(它们甚至可能要求该字节数为2的倍数或4)。在许多应用程序中,需要散列的数据将与不能包含在散列中的数据混合在一起 - 例如缓存值,文件句柄,对其他数据的指针/引用或虚拟分派表等。一个常见的解决方案是分别散列所需的字段并组合散列键 - 可能使用exclusive-or。因为可能存在应该在与不应该散列的其他数据相同的内存字节中进行散列的位字段,所以有时需要自定义代码来提取这些值。尽管如此,即使事先需要一些复制和填充,每个单独的字段最终都可以使用md5,SHA-1或其他任何字段进行哈希处理,并且这些哈希值可以类似地组合在一起,因此这种复杂性并不能真正明确地排除您的方法。对此很感兴趣。

  

我能想到的唯一理由是他们需要说大键说32位。

所有其他条件相同,密钥越大越好,但如果哈希函数在数学上是理想的,那么它的任何N位 - 其中2 ^ N> = #hash buckets - 将产生最小的冲突。

  

但仍然避免碰撞,因此查找肯定会是O(1)。

再次,如上所述错误。

(顺便说一句......我强调上面几个地方的通用目的。这只是因为有些琐碎的案例你可能会对你需要散列的键有一些了解,这可以让你完美地定位它们。可用的哈希桶。例如,如果你知道密钥是数字1000,2000,3000等,最多100000并且你有至少100个哈希桶,你可以简单地将哈希函数定义为x / 1000并且知道你' d有完美的哈希sans碰撞。这种知道你所有的键都映射到不同的哈希表桶的情况被称为“完美哈希” - 根据你的问题标题 - 像md5这样的好的通用哈希不是一个完美的哈希,并且事实上,在不知道完整的可能键集的情况下讨论完美哈希是没有意义的。)