1

我正在构建一个哈希表,其中的键是一个电话号码(这里有一些):

6948060987
6960780800
6963208768
6944870406
6947279288
6953691771
6956094283
6947092062
6960086297
6947719197
6951516975
6957531584
6969211184
6963238579
6957054322
6952077216
6956907738

条目数将为 200、2000、20000 和 2000000,并且条目是唯一的。

关于桌子的大小,我正在关注这个答案。

char我将电话号码存储为's数组。我注意到所有的数字都以 69 开头,所以我可以在散列函数中跳过它们。

我的尝试是取数字的总和并对哈希表中的单元格数进行取模,但(在纸面上)这似乎是一个坏函数,因为有很多冲突。

我应该如何修改我的哈希函数以获得更好的结果(更少的冲突)?

4

1 回答 1

3

为什么你需要一个非标准的哈希函数?

有很多散列函数经过了很好的测试并且具有已知的属性,可以很好地用于任何输入,因此也可以很好地用于电话号码,毕竟电话号码是 ASCII 字符串的子集。您的应用程序是否对时间至关重要,以至于您需要设计自己的哈希函数并冒更多冲突的风险?如果不是,为什么不使用众所周知的散列函数之一?

例如,如果您需要具有可加密证明的抗碰撞性的东西,请使用 SHA-256(如果需要,可以截断)。如果您不担心对手,请使用Universal hashing 之类的东西。除非您的问题非常专业,否则您最好使用其他人经过良好测试的哈希算法,而不是尝试自己发明一个。

一个更简单的哈希是perl used 的原始哈希,它的工作原理如下:

# Return the hashed value of a string: $hash = perlhash("key")
# (Defined by the PERL_HASH macro in hv.h)
sub perlhash
{
    $hash = 0;
    foreach (split //, shift) {
          $hash = $hash*33 + ord($_);
    }
    return $hash;
}

在英语中,它取当前的哈希值,乘以 33,然后加上下一个字符的 ASCII 值。这不是一个很好的哈希,但它在 perl 上工作了很长时间。

于 2014-10-14T21:31:24.797 回答