可先科普下质数的概念:质数,也就是素数,就是指一个大于1的自然数,约数(因数)只有1和它自己,否则叫合数。
除留取余,就是哈希函数将关键字被某个不大于哈希表长m的数p除后所得余数为哈希地址。这是最常用、也最简单的构造哈希函数的方法。当然,也可以对关键字直接取模,也可以折叠、平方取中等运算后取模。那么问题来了,这个p取多大呢?p的取值不好,会不会造成哈希函数的不均匀?先看一个简单的例子:
有一个数组: 1, 3,5,7,9,11,13, 15,17,19,21, 23,25 我们选取p为4(=2*2,含有约数2),即有四个桶,经过哈希函数后,
很明显求余结果都为1或者3,:都落在哈希地址为1的桶里,很明显这是不合理的。
为什么会出现这种情况呢,那么p应该怎么选取呢?
我们发现,上面数组求余后的哈希地址都为1,3,1,3,哈希地址的值不是1,就是3,所有哈希地址的差值不是2就是0,即3-3=0,1-1=0,3-1=2,恰好p=4的约数也是2,这个是不是巧合呢?
我们换一个数组来试一试:
数组b: 28,35,63,77,105,我们取p=21(3*7)
哈希地址: 7 ,14, 0, 14, 0
我们的数组差值都是7的倍数,哈希地址也是7的倍数,即哈希地址的差值也是0,7或者7的倍数,巧合的是我们的p也包含因数7。是不是只要p包含一个因数,这个因数对数组差值为这个因数的倍数整除的结果差值也是这个因数的倍数呢?
下面我们假设,p=tq,t为常数,q为某个质数,关键词的差值是q的倍数,那么h(x)-h(y)=q*n,
哈希地址 (h(x)-h(y))%p= q*n%(t*q)=(q*n-t*q*r)=q*(n-tr); t位整除的值。
因此,均散列在差值为q的地址上。
这样,如果散列值的因数越多,可能导致的散列分布越不均匀,所以p的选择需要选择约数少的数值,什么数值的约数最少呢?当然是只有1和它自己的质数了。所以往往将桶个数设置为质数或不包含小于20的质因数的合数。