避免key的繁琐比较,是种高效的查找数据结构,记录之间无关联
-
哈希函数/散列函数
存储位置=f(关键字)
不需遍历或比较,直接找到存储位置。
存取使用同一个散列函数:存储时,通过散列函数计算记录的散列地址,存储记录;查找时,通过散列函数计算记录的散列地址,查找记录
-
散列函数的评判
(1)计算简单,时间短(2)散列地址分布均匀,可以有效利用存储空间,减少冲突
(3)雪崩效应key的微小变化可以使f(key)发生很大的变化
- 哈希表/散列表
采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间被称为哈希表。
-
几类散列函数
(1)直接定址法
取关键字的线性函数值f(key)=a*key+b
优点:简单,均匀,不冲突
缺点:需要知道关键字的分布情况
适用范围:查找表小且连续的情况
(2)数字分析法
抽取key的一部分,再用反转、左移、右移、叠加进行辅助
适用范围:关键字位数比较大,关键字若干位分布较均匀
(3)平方取中法
对key的平方值取中间几位作为散列地址
适用范围:不知道关键字分布,位数不是很大
(4)折叠法
对key分成几段求和,再取末尾几位
(5)除留余数法
f(key)=key mod p(p<=m) 散列表表长为m
根据经验,为减少冲突,p为小于或等于表长m(最好接近m)的最小质数或不包含小于20质因数的合数。
(6)随机数法
f(key)=random(key) random为伪随机函数
适用范围:关键字的长度不等
-
冲突
key1!=key2,却有f(key1)=f(key2),将key1和key2称为散列函数的同义词
-
处理冲突的方法
(1)开放定址法
发生冲突就找下一个空的散列地址
线性探测法: fi(key)=(f(key)+di)mod m di=1,2,。。。m-1
堆积现象:不是同义词却需要争夺同一个地址,比如说因为冲突所以需要把地址不断往后挪,往后挪的时候就会发生堆积
二次探测法: fi(key)=(f(key)+di)mod m di=1^2,-1^2,2^2,-2^2,...q^2,-q^2 q<=m/2
可以双向寻找空位置,使用平方可以使关键字不都聚集在某一块区域
随机探测法: 对位移量di使用随机函数(这里指伪随机)取得
(2)再散列函数法
准备多个散列函数
fi(key)RHi(key) i=1,2,...,k RHi指不同的散列函数
优点:关键字不聚集
缺点:计算时间大
(3)链地址法/拉链法
将关键词为同义词的记录存储在一个单链表中,有冲突就增加节点,保证解决冲突但引入了遍历单链表的损耗。
(4)公共溢出区法
分成基本表和溢出表,将冲突的关键字存储到溢出表中。
查找时,如果相应位置的值不相等,就到溢出表中进行顺序查找
适用范围:冲突数据很少
-
散列表查找性能相关因素
散列函数是否均匀
处理冲突的方式:比如链地址法 优于 二次探测法 优于 线性探测法
散列表的填装因子=填入表中记录个数/散列表长度 一般是浪费一点空间,使平均长度限定在一个范围内
参考文献:
《大话数据结构》