索引
哈希表的概念
哈希函数的构造方法
处理冲突的方法–链地址法
处理冲突的方法–开放地址法
哈希表的实现
哈希表的查找性能
4.1、哈希表的概念
把关键字集合*K*到一个有限的连续的地址集(区间)D的映射关系表示为:
K为主关键字集合,H称为哈希函数或散列函数。按哈希函数构建的表称为哈希表。D的大小m称为哈希表的地址区间长度。
先看一个简单的例子:
假设要建立一个地址区间长度为13的哈希表,哈希函数为
其中函数Ord为求字母再在字母表中的序号。例如,字母A在字母表中的序号为Ord(‘A’)=1。现将关键字依次为Zhao、Qian、Sun、Li、Wu、Chen、Han的7个记录插入该哈希表。第一个关键字Zhao的哈希函数值为
将Zhao存入12号单元。类似地,依次将各关键字映射到相应单元,如图所示:
4.2、哈希函数的构造方法
若哈希函数构造地不均匀,将会出现不同关键字的哈希函数值可能相同,出现冲突现象。哈希函数越均匀,发生冲突的概率越低。 下面介绍几种常用的哈希函数构造方法:4.2.1、直接定址法
最简单的直接定址法直接用关键字key作为哈希地址,即H(key)=key。
例如一个儿童人口统计表,记录了从0岁到12岁的儿童人口数目,以年龄作为关键字,哈希函数取关键字自身,如表所示:
地址 | 0 | 1 | … | 11 | 12 |
---|---|---|---|---|---|
年龄 | 0 | 1 | … | 11 | 12 |
人数 | 980 | 800 | … | 495 | 107 |
要查找11岁的儿童人数时,直接定位第11项即可。
虽然这种哈希函数简单,且不会发生冲突,但在实际应用中,关键字很少是连续的,采用这种特殊的哈希函数会造成哈希表空间浪费。一般情况下,直接定址法可通过对关键字的缩放和平移获得合适的地址区间,即线性函数 H(key)= a *key + b
其中,a为缩放系数,b为平移系数。
以下算法给出了直接定制哈希函数的实现
int hast_d(int key){
return a * key + b; //a为缩放系数,b为平移系数
}
例如某地区要统计年龄从18岁到60周岁的人数,就可以采用将关键字减去18来作为数据的存储单元,即a=1,b=-18。人数统计的哈希函数示例
地址 | 0 | 1 | … | 11 | 12 |
---|---|---|---|---|---|
年龄 | 18 | 19 | … | 59 | 60 |
人数 | 90 | 80 | … | 40 | 10 |
4.2.2、除留余数法
对于地址区间长度为m的哈希表,除留余数法取某个不大于m数p为模,将哈希函数定义为H(key)= key % p (p<=m)。
除留余数法简单常用,不仅可以对关键字直接取模,也可以在折叠、平方取中等运算后再取模。值得注意的是,模p的选择十分重要。 理论研究表明,当模p取不大于m且最接近m的素数,或不包含小于20的质因子的合数时,可使哈希地址尽可能均匀地分布在地址空间。模p建议值示例
地址区间长度m | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1000 |
---|---|---|---|---|---|---|---|---|
模p | 7 | 13 | 31 | 61 | 127 | 251 | 503 | 997 |
以下算法给出了除留余数法的哈希函数的实现
int hash_m(int key){
return key % p;
}
为保证求得的哈希函数值在地址区间长度范围以内,其他哈希函数构造方法常把除留余数法作为其最后一步运算。
4.2.3、数字分析法
当关键字的位数很多时,可以通过对关键字的各位进行分析,去掉分布不均匀的位,将分布均匀的位提取出来作为哈希值。数字分析法取关键字中某些取值分别较均匀的数位作为哈希地址,适合于关键字位数较多,且能预测关键字各位发布均匀度的情况。
例如
显然数字分析法仅适用于事先知道表中所有关键字每一位数值的分布情况,它完全依赖于关键字集合。
4.2.4、折叠法
折叠法将关键字分割成位数相同的若干部分(最后一部分的位数可以较少),并取各部分的叠加和(舍去进位)作为哈希函数。折叠法适用于关键字位数较多且每一位数字分布大致均匀的情况。
分割后,可采用移位叠加或Z形叠加:移位叠加是将分割后每一部分的最低位对齐,然后相加;Z形叠加式从一端向另一端沿分割界来回折叠,然后对齐相加。
下面算法给出移位叠加的哈希函数的实现:
int hash_s(long key){
int i,j=1,qu,sum=0;
for(i=0;i<w;i++)//按w位数分割
j*=10;
while(key!=0){
qu=key%j;
sum+=qu;
key/=j;
}
}
设哈希表的地址区间长度为10000,关键字key=401108105302169891,允许的地址空间为4为十进制数,w=4,则这两种叠加情况如图所示:
4.2.5、平方取中法
平方取中法先取关键字的平方,然后根据哈希表地址区间长度m的大小,选取平方数的中间若干位作为哈希地址。该方法通过取平方扩大关键字之间的差别,而平方值的中间若干位和这个数