散列方法
不用比较就能直接计算出记录的存储地址,从而找到所要的结点
Hash表
1)、定义
根据设定的散列函数和相应解决冲突的方法为一组结点建立的一张表,表中的结点的存储位置依赖于设定的散列函数和处理冲突的方法
如图:
2)、基本思想
设计1个hash函数,计算hash函数,其函数值恰好是key在Hash表中的地址
即,locate(key)= hash(key)
3)、冲突
若对于不同的键值k1和k2,且k1≠ k2,但hash(k1)= hash(k2)
即,k1和k2具有相同的散列地址,这种现象称为冲突
称k1、k2为同义词
4)、表长(m)的选取
设关键字个数为n,则:
n/m ≈ 3/4
5)、装载/负载因子
α = 表中填入的记录数 / Hash表的长度
Hash函数的构造方法
原则:使产生冲突的可能性降到尽可能的小
1)、直接定址法
哈希函数为关键字的线性函数
如:hash(key)= a * key + b
2)、数字分析法
若关键字集合中的每个关键字都是由s位数字组成,分析关键字集中的全体,并从中提取分布均匀的若干位或它们的组合作为地址
3)、平方取中法
若关键字的每一位都有些数字重复出现频度很高的现象,则先求关键字的平方值,以通过“平方值”过大差别,同时平方值的中间几位受到整个关键字中各位的影响
如:
4)、折叠法
若关键字的位数比较长,则可将其分割成几个部分,然后取它们的叠加和为哈希地址
两种处理方法,对关键字0442205864
①移位叠加
②间界叠加
5)、除留余数法
选择一个适当的正整数p,用p去除关键值,取其余数作为散列地址
hash(key)= key%p (p ≤ m)
p值的选取:小于m(表长)的最大质数
6)、随机数法
hash(key)= Random(key)
冲突的处理
1)、链地址法
将具有相同散列地址的记录都存储在同一个线性链表中
如图:使用hash(key)= key%17 (m=17、p=17)
2)、开放定址法
当冲突发生时,使用某种方法在散列表中形成一个探查序列,沿着此序列逐个地址去探查,直到找到一个开放的地址(未存放数据),将发生冲突的键值放到该地址中
①线性探测法
对给定的关键值k,若地址d(即hash key)发生冲突,则依次探查:
d+1、d+2、…、m-1、0、1、…、d-1
例,集合:{14,1,68,27,55,23,11,10,19,20,79,84}
若设表长为16,则使用hash(key)= key%13
②二次探测法
对给定的关键值k,若地址d(即hash key)发生冲突,则依次探查:
d+1、d-1、d+4、d-4、d+9、d-9、…
例,集合:{14,1,68,27,55,23,11,10,19,20,79,84}
若设表长为17,则使用hash(key)= key%17
③再散列探测法
对给定的关键值k,若地址d(即hash key)发生冲突,则依次探查:
(d+h(k))%m、(d+2h(k))%m、(d+3h(k))%m、…
h的选取方法,保证h(k)和m互质:
若m为素数:h(k) = k%(m-2) + 1
若m为2^i:h(k) = 1 ~ m-1 之间的任意奇数
3)、公共溢出区法
对具有相同散列地址的记录,将第1个放在hash表中,其余的都存储在同一个溢出区中
例,集合:{14,1,68,27,55,23,11,10,19,20,79,84}
若设表长为17,则使用hash(key)= key%17
Hash表的查找
查找过程和建表过程一致