6.6散列表
定义:根据给定的关键字来计算出关键字在表中的地址的数据结构。也就是说,散列表建立了关键字和存储地址之间的一种直接映射关系。
散列函数:一个把查找表中的关键字映射成该关键字对应地址的函数,记为Hash(key)=Addr。
冲突:散列函数可能会把两个或者两个以上的不同关键字映射到同一地址,这种情况为“冲突”,这些发生碰撞的不同关键字称为同义词。
构造散列函数的Tips:
1)散列函数的定义域必须包含全部需要存储的关键字,而值域的范围则依赖于散列表的大小或地址范围。
2)散列函数计算出来的地址应该能等概率,均匀的分布在整个地址空间,从而减少冲突的发生。
3)散列函数应该尽量简单,能够在较短时间内计算出任意关键字的散列地址。
常用的Hash函数的构造方法:
1.直接定址法:直接取关键字的某个线性的函数值为散列地址,散列函数为H(key) =a*key+b。式子中,a和b是常数。这种方法最简单,并且不会产生冲突。
2.除留余数法:假定撒列表的表长为m,取一个不大于m当最接近或等于m的质数p,利用以下公式转换为散列地址。散列函数为H(key)=key&p。
关键在于选择p,使每个关键字通过该函数转换后都能等概率的映射到散列空间上的任意地址,从而减少冲突的可能性。
3.数字分析法:设关键字是r进制(如十进制),而r个数码在各位出现的频率不一定相同,可能在某些位数上分布均匀些,每种数码出现的机会均等;而在某些数位上分布不均匀,只有某几位数码经常出现,则应该选取数码分布较为均匀的若干位作为散列地址。这种方法适合一直的关键字集合。
例子:
4.平方取中法:去关键字的平方值的中间几位作为散列地址,具体区取几位看实际情况,这种方法得到的散列地址于关键字的每一位都有关系,使得到的散列地址分布比较均匀。
5.折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以短一些),然后取这几部分的叠加和作为散列地址,这种方法称为折叠法。
关键字位数很多,而且关键字中的每一位上数字分布大致均匀时,可以采用折叠法得到散列地址。
冲突解决办法:
1.开放地址法:
将产生冲突的Hash地址作为自变量,通过某种冲突解决函数得到一个新的空闲的Hash地址。
1)线性探测法:冲突发生时,顺序查看表中的下一个单元(但探测到地址m-1时探测地址是表首地址0),直到找到一个空闲的单元(表未满时,一定能找到)
2)平方探测法:
3)再散列法:
4)伪随机序列法:
2.拉链法:
对于不同的关键字可能会通过散列函数映射到同一地址,为了避免冲突,可以把所有的同义词存储在一个线性表中,这个线性表尤其散列地址唯一标识。拉链法适用于经常进行插入删除的情况。
3散列表的查找过程:类似于构建散列表,给定一个关键值Key.
4.散列表的查找性能:和装填因子有关
装填因子:
例子: