为什么这是一个糟糕的哈希函数?

Why is this a bad hash function?

我目前正在介绍哈希和哈希表,我想知道为什么像下面这样的东西被认为是一个糟糕的哈希函数(伪代码):

function hash(String_t word, Int table_size)
    i = randomly generated number with 0<i<table_size 
    j = ASCII code of the first letter of word

    return i * j % table_size

假设可以在函数调用期间存储 i 的值以实现一致性(例如使用 C 中的 static 关键字将 i 的值存储在函数内范围),为什么这是一个糟糕的散列函数?

一个好的哈希函数应该适用于各种输入大小,唯一的条件是 table 大小是输入数量的常数倍。由于以下几个原因,这不符合该标准:

  1. 哈希值仅由首字母决定。因此,可能的哈希值总数受可能的第一个字母的数量限制,该数量很小。为大量输入选择较大的 table 尺寸没有任何效果:您仍然会遇到大量碰撞。

  2. 由于单词的首字母远非均匀分布,所以会发生很多碰撞。至少在定义你的函数时使用单词的所有字母,但你真的需要更多的建议来挽救这个结构。

  3. 定义 d = gcd(i, table 大小)。在某些情况下,d 会大于 1,在这些情况下,table 的每 d 个元素中只有一个有机会被填充:其他的将被浪费掉 space(因此更多的碰撞)。也就是说,只有 0, d, 2d, 3d, ... 可能是哈希值。至少限制为 d=1 的 i 值以防止这些退化情况。

  4. i 乘以 j 的最大值偶尔会小于 table 大小(当 i 较小时),这意味着 table 的顶端永远不会被感动。更多浪费space.

人们通常会尝试提出一般情况下运行良好的散列函数,并且您可以证明它们的优点。在这里你有一些针对一个非常具体的案例的东西,对我来说最明显的是消极的案例,所以非常非常怀疑你能证明这个结构的任何积极因素。