C 电话号码的哈希函数

C 电话号码的哈希函数,c,hash,hash-function,C,Hash,Hash Function,我正在构建一个哈希表,其中键是一个电话号码(这里有一些): 参赛作品数量将为200、2000、20000和2000000,参赛作品将是独一无二的 关于桌子的大小,我下面回答 我将电话号码存储为字符的数组。我注意到所有数字都以69开头,所以我可以在哈希函数中跳过它们 我的尝试是取数字之和,并对哈希表中的单元格数进行模运算,但(理论上)这似乎是一个糟糕的函数,因为存在许多冲突 如何修改哈希函数以获得更好的结果(减少冲突)?为什么需要使用非标准哈希函数 有很多经过良好测试的哈希函数,它们具有已知的属性

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

参赛作品数量将为200、2000、20000和2000000,参赛作品将是独一无二的

关于桌子的大小,我下面回答

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

我的尝试是取数字之和,并对哈希表中的单元格数进行模运算,但(理论上)这似乎是一个糟糕的函数,因为存在许多冲突


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

为什么需要使用非标准哈希函数

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

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

更简单的散列是,其工作原理如下:

# 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中工作了很长一段时间。

您可以使用电话号码的整数表示作为散列。@AlexD这将避免冲突。。。除非两个人碰巧共用一个电话号码,否则会发生什么情况?你是说@AlexD函数会找到整数表示?Jon电话是唯一的,我会更新。@G.Samaras是的,只是
atoi
或类似的。@JonKiparsky当电话号码已经被选为散列键时,拥有相同电话号码的两个人是无关的。问题是为所选的键选择一个好的散列函数。我说明了为什么要修改我的散列函数(它会导致许多冲突)。我想使用你描述的函数。我不是在寻找超级理想的散列函数,而是一个好的散列函数。SHA-256对我来说似乎太多了。链接看起来不错
p
hash\u表。我猜是size
。什么是
a
?@G.Samaras对不起-我的意思是“为什么你需要一个非标准的散列函数”,也就是说,为什么不从标准的散列函数开始并坚持使用它呢。我已经澄清了答案,没关系。关于我提到的参数,请看代码上面的句子
p
是一个素数,远远大于255(每个值的最大值)或箱数,
a
是随机选择的,小于
p
。您必须在最后取整批
mod m
,其中
m
是箱子的数量。我还发布了perl使用的一个更简单的算法(同样,您必须在最后获取结果
mod m
。我如何选择
p
?随机但有限制?
# 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;
}