7.除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址,即设定哈希函数为 Hash(key)=key mod p (p≤m),其中,除数p称作模。
除留余数法不仅可以对关键字直接取模,也可以在折叠、平方取中等运算后取模。对于除留余数法求哈希地址,关键在于模p的选择。使得数据元素集合中每一个关键字通过该哈希函数映射到内存单元的任意地址上的概率相等,从而尽可能减少发生哈希冲突的可能性。
理论研究表明,除留余数法的模p取不大于表长且最接近表长m素数时效果最好,且p最好取1.1n~1.7n之间的一个素数(n为存在的数据元素个数)。例如:当n=7时,p最好取11、13等素数。 又例图(5):
表长m | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1000 |
模p | 7 | 13 | 31 | 61 | 127 | 251 | 503 | 997 |
由于除留余数法的地址计算方法简单,而且在许多情况下效果较好。[2]↑
例9,公司有236个员工,而员工编号介于1000到9999,除留余数法就是员工编号除以数据个数236后,去余数即为数据的位置。编号5428员工的数据(编号5428除以236取余数得0)放数据中的第一笔,编号3512员工数据(编号3512除以236取余数得8)放数据中的第九笔…依次类推。
8.随机乘数法
亦称为“乘余取整法”。随机乘数法使用一个随机实数f,0≤f<1,乘积f*k的分数部分在0~1之间,用这个分数部分的值与n(哈希表的长度)相乘,乘积的整数部分就是对应的哈希值,显然这个哈希值落在0~n-1之间。其表达公式为:Hash(k)=「n*(f*k%1)」其中“f*k%1”表示f*k 的小数部分,即f*k%1=f*k-「f*k」[5] ↑
例10,对下列关键字值集合采用随机乘数法计算哈希值,随机数f=0.103149002 哈希表长度n=100得图(6):
k | f*k | n*((f*k)的小数部分) | Hash(k) |
319426 | 32948.47311 | 47.78411 | 47 |
718309 | 74092.85648 | 86.50448 | 86 |
629443 | 64926.41727 | 42.14427 | 42 |
919697 | 84865.82769 | 83.59669 | 83 |
此方法的优点是对n的选择不很关键。通常若地址空间为p位就是选n=2p.Knuth对常数f的取法做了仔细的研究,他认为f取任何值都可以,但某些值效果更好。如f=(-1)/2=0.6180329...比较理想。[8] ↑
9.字符串数值哈希法
在很都情况下关键字是字符串,因此这样对字符串设计Hash函数是一个需要讨论的问题。下列函数是取字符串前10个字符来设计的哈希函数
Int Hash _ char (char *X)
{
int I ,sum
i=0;
while (i 10 && X[i])
Sum +=X[i++];
sum%=N; //N是记录的条数
}
这种函数把字符串的前10个字符的ASCⅡ值之和对N取摸作为Hash地址,只要N较小,Hash地址将较均匀分布[0,N]区间内,因此这个函数还是可用的。对于N很大的情形,可使用下列函数
int ELFhash (char *key )
{
Unsigned long h=0,g;
whie (*key)
{
h=(h<<4)+ *key;
key++;
g=h & 0 xF0000000L;
if (g) h^=g>>24;
h & =~g;
}
h=h % N
return (h);
}
这个函数称为ELFHash(Exextable and Linking Format ,ELF,可执行链接格式)函数。它把一个字符串的绝对长度作为输入,并通过一种方式把字符的十进制值结合起来,对长字符串和短字符串都有效,这种方式产生的位置不可能不均匀分布。[7] ↑
10.旋转法
旋转法是将数据的键值中进行旋转。旋转法通常并不直接使用在哈希函数上,而是搭配其他哈希函数使用。
例11,某学校同一个系的新生(小于100人)的学号前5位数是相同的,只有最后2位数不同,我们将最后一位数,旋转放置到第一位,其余的往右移。
新生学号 | 旋转过程 | 旋转后的新键值 |
5062101 | 5062101 | 1506210 |
5062102 | 5062102 | 2506210 |
5062103 | 5062103 | 3506210 |
5062104 | 5062104 | 4506210 |
5062105 | 5062105 | 5506210 |
如图(7)
运用这种方法可以只输入一个数值从而快速地查到有关学生的信息。[9] ↑
11.伪随机数法
伪随机数法是将利用数据的键值经过随机数法的运算后的结果作为数据存储的位置。其公式如下(a和c为质数):
Y=(a * Key + c)mod 数组的大小
例12,某公司的某女员工的编号是321547,现该公司共有107个女职工,我们取a=13,c=5则
Y=(13*321547+5)%107
=(4180111+5)%107
=54
则取54当作该员工数据存储的位置。[10] ↑
小 结
有许多种不同的哈希函数设计方法,这里主要讨论几种常用的不同类型关键字的希函数设计方法:直接定址法、数字分析法、折叠法、平方取中法、减去法、基数转换法、除留余数法、随机乘数法、字符串数值哈希法、伪随机数法、旋转法。
尽管哈希函数的构造方法有很多,但不同的方法适用于不同的情况。如:当键字是字符串时可以用字符串数值哈希法构造哈希函数;当关键字是整数类型时就可以用除留余数法、直接定址法和数字分析法等设计哈希函数;而关键字是小数类型常用伪随机数法来构造哈希函数等。
原文地址:http://wenku.baidu.com/view/61b121c06137ee06eff918c1.html