前面的文章介绍了线性表及树表的查找算法:
这篇文章则介绍散列表(即哈希表)的查找方法。
一,哈希表的构造
基本概念
•优点:查找速度极快O(1),查找效率与元素个数n无关。
例1:
若将学生信息按如下方式存入计算机,如:
将2001011810201的所有信息存入V[01]单元;
将2001011810202的所有信息存入V[02]单元;
……
将2001011810231的所有信息存入V[31]单元
查找2001011810216的信息,可直接访问V[16]!
例2:
数据元素序列(14,23,39,9,25,11),若规定每个元素k的存储地址H(k)=k,请画出存储结构图。
如何进行哈希表的查找?
根据哈希函数H(k)=k
查找key=9,则访问H(9)=9号地址,若内容为9则成功;
若查不到,则返回一个特殊值,如空指针或空记录
我们需要知道以下概念:
哈希方法(杂凑法)
选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;
查找时,由同一个函数对给定值k计算地址,将k与地址单元中元素关键码进行比,确定查找是否成功。
哈希函数(杂凑函数):哈希方法中使用的转换函数。
哈希表(杂凑表):按上述思想构造的表。
冲 突:不同的关键码映射到同一个哈希地址 。key1 !=key2,但H(key1)=H(key2)
同义词:具有相同函数值的两个关键字。
具体什么是冲突呢?我们来看一个例子:
冲突是不可避免的,那么我们如何才能减少冲突?
(1)构造好的哈希函数
(2)制定一个好的解决冲突方案
构造好的哈希函数
(a)所选函数尽可能简单,以便提高转换速度;
(b)所选函数对关键码计算出的地址,应在散列地址集中致均匀分布,以减少空间浪费。
构造好的哈希函数,我们需要考虑以下因素:
根据元素集合的特性构造
要求一:地址空间尽量小
要求二:均匀
则有以下方法:
1.直接定址法 2.数字分析法 3.平方取中法 4.折叠法 5.除留余数法 6.随机数法
1. 直接定址法
Hash(key) = a·key + b (a、b为常数)
优点:以关键码key的某个线性函数值为哈希地址,不会产生冲突。
缺点:要占用连续地址空间,空间效率低。
例: {100,300,500,700,800,900},哈希函数Hash(key)=key/100
2.除留余数法
Hash(key)=key mod p (p是一个整数)
通过计算出散列表中元素除以7得到的余数作为存储地址的位置
如果两个数的余数一样时,就出现了冲突,那么如何处理冲突呢?
处理冲突的两种方法:
1.开放地址法(开地址法)
基本思想:有冲突时就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。
A.线性探测法
Hi=(Hash(key)+di) mod m ( 1≤i < m )
其中:m为哈希表长度
di 为增量序列 1,2,…m-1,且di=i
一旦冲突,就找下一个空地址存入旦冲突,就找下一个空地址存入
例:
关键码集为 {47,7,29,11,16,92,22,8,3},
设:哈希表表长为m=11;
哈希函数为Hash(key)=key mod 11
我们可以得到用线性探测法处理冲突的过程:
线性探测法的优点:只要哈希表未被填满,保证能找到一个空地址单元存放有冲突的元素。
缺点:可能使第i个哈希地址的同义词存入第i+1个地址,这样本应存入第i+1个哈希地址的元素变成了第i+2个哈希地址的同义词,……,产生“聚集”现象,降低查找效率。
为了解决这种现象,我们引入了另一种方法处理冲突:
B.二次探测法
Hi=(Hash(key)±di) mod m
其中:m为哈希表长度,m要求是某个4k+3的质数;
di为增量序列 12,-12,22,-22,…,q2
例:
关键码集为 {47,7,29,11,16,92,22,8,3},
设: 哈希函数为Hash(key)=key mod 11
Hash(3)=3,哈希地址冲突,由
H1=(Hash(3)+1*1) mod 11=4,仍然冲突;
H2=(Hash(3)+(-1)*(-1)) mod 11=2,找到空的哈希地址,存入。
C.伪随机探测法
Hi=(Hash(key)+di) mod m ( 1≤i < m )
其中:m为哈希表长度
di 为随机数
2.链地址法(拉链法)
基本思想:相同哈希地址的记录链成一单链表,m个哈希地址就设m个单链表,然后用用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。
链地址法建立哈希表步骤 :
step1 取数据元素的关键字key,计算其哈希地址。若该地址对应的链表为空,则将该元素插入此链表;否则执行step2解决冲突。
step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若该地址对应的链表为不为空,则利用链表的前插法或后插法将该元素插入此链表。
链地址法的优点:
同义词不会冲突,无“聚集”现象
链表上结点空间动态申请,更适合于表长不确定的情况
二,哈希表的查找
例:
已知一组关键字(19,14,23,1,68,20,84,27,55,11,10,79)
哈希函数为:H(key)=key MOD 13, 哈希表长为m=16,
设每个记录的查找概率相等
(1) 用线性探测再散列处理冲突,即Hi=(H(key)+di) MOD m
ASL=(1*6+2+3*3+4+9)/12=2.5
(2) 用链地址法处理冲突
关键字(19,14,23,1,68,20,84,27,55,11,10,79)
ASL=(1*6+2*4+3+4)/12=1.75
对于这个例子,我们思考是用无序表查找还是有序表折半查找?ASL又如何?
从哈希表的查找效率分析
使用平均查找长度ASL来衡量查找算法,ASL取决于
哈希函数
处理冲突的方法
哈希表的装填因子
a 越大,表中记录数越多,说明表装得越满,发生冲突的可能性就越大,查找时比较次数就越多。
我们可以得到以下结论:
哈希表技术具有很好的平均性能,优于传统技术
链地址法优于开地址法
除留余数法优于其它哈希函数