【问题标题】:Hash function for phone numbers电话号码的哈希函数
【发布时间】:2014-12-09 17:58:29
【问题描述】:

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

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

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

关于桌子的大小,我在关注this的回答。

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

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

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

【问题讨论】:

  • 您可以使用电话号码的整数表示形式作为其哈希值。
  • @AlexD 这样可以避免冲突...除非两个人碰巧共享一个电话号码,这可能会发生
  • 所以你的意思是@AlexD 该函数会找到整数表示?乔恩的手机是独一无二的,我会更新的。
  • @G.Samaras 是的,只是atoi 或类似的。
  • @JonKiparsky 当电话号码已被选为哈希键时,两个拥有相同电话号码的人是不相关的。问题是为所选键选择一个好的散列函数。

标签: c hash hash-function


【解决方案1】:

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

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

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

一个更简单的哈希是the original hash 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 上工作了很长时间。

【讨论】:

  • 我说明了为什么要修改我的哈希函数(它会导致很多冲突)。我想使用您描述的功能。我不是在寻找超理想的哈希函数,而是在寻找一个好的哈希函数。 SHA-256 对我来说似乎太多了。链接看起来不错。 phash_table.size 我猜。 a 是什么?
  • @G.Samaras 抱歉 - 我的意思是“你为什么需要一个非标准的哈希函数”,即为什么不开始并坚持使用标准的哈希函数。我已经澄清了答案。
  • 没关系。我提到的参数呢。
  • 见代码上面那句话。 p 是一个比 255(每个值的最大值)或箱数大得多的素数,a 是随机选择的,并且小于 p。您将不得不在最后取整批mod m,其中m 是垃圾箱的数量。我还发布了 perl 使用的更简单的算法(同样,您必须在最后获取结果 mod m
  • 我如何选择p?随机但有限制?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
相关资源
最近更新 更多