散列表长度和素数的关系


看到很多散列表(hash table)的实现中,长度都是一个素数。至于为什么一定要用素数,一下子也没想出所以然来。上网搜索了一下相关的文章,发现很多人也在讨论这个问题。

http://www.cs.unm.edu/~saia/numtheory.html

http://www.codexon.com/posts/hash-functions-the-modulo-prime-myth

http://www.codexon.com/posts/hash-functions-the-modulo-prime-myth-2

http://blog.csdn.net/ilibaba/archive/2009/03/05/3960142.aspx

长度是否要是素数,能不能是合数,这个问题大家的意见得不到统一。支持用素数的人的理由是,素数可以使得散列的分布更加均匀。

自己总结一下看这些文章的心得。一个散列运算可以等价如下式:

hash(k) = mix(k) mod m

散列计算中,求余往往是最后一步,因为没有机器拥有无限的内存,所以必须把结果放入到有限的桶(bucket)中。求余前的运算,假如混淆(mix)得比较好的话,那么m使用素数还是合数,分布是一样的。假如混淆(mix)得不够好的话,那么一个素数可以把一些common pattern加以区别。至于什么样的数据混淆用什么样的mix算法比较好,这个得经统计才可以得出结论。总的来讲,使用一个素数总没有错,虽然运行慢了点,却可以得到相对较好的统计特性。个人看法。

Knuth的The Art of Computer Programming中,也用的是一样的理由推荐用素数的m。手上没有书,他应该没有提到合数的问题。上面也仅仅是我个人的一些想法,没有经过严格的证明,我也没有能力去证明。当然,很欢迎有人来指正我的错误。

手上有《算法导论》,第十一章散列表,对这个问题也没有给出严格的证明。但是它提到这样的一个问题,若m=2^p-1,则所有以2^p为基数的解释的字符串,无论字符位置怎么变化,得出的散列值都是一样的。这个证明比较简单,用同余的性质就可以证明,最后的值,其实是各个字符值的和再对m取余,所以散列值不会随字符的位置发生变化。

UPDATE:

StackOverflow上也有对这个问题的讨论。

http://stackoverflow.com/questions/1145217/why-should-hash-functions-use-a-prime-number-modulus

上面的文章的观点和我总结出来的基本一致。


from http://hi.baidu.com/vwin044/item/374ee83d11aad5d02784f4c0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值