hash函数的构造方法
1.直接定址法
将关键字带入线性函数中如H(k)=a*k+b,其中k为关键字的值,a,b为常数,H(k)为所要求的地址。
2.除留余数法
H(k)=k%a 其中a为不大于表长的数,且a为质数时冲突较少,我一直没明白。
3.平方取中法
取关键字平方后的中间几位作为hash地址,这种方法可以使得关键字的每一位取值影响到求得的hash地址。当然,求出的地址超出表的范围可以对表长取摸。
4.折叠法
在关键字位数较多时,可以采用折叠法,这种方法是将关键字分成长度相同的几部分,最后几位长度不够时可以补0,然后算这几部分的叠加和。当然算叠加和的方式有多种,常见的是每段最后一位对其或者相邻2段首尾对齐。在超出表长时可以取摸。
5.数值分析法
在知道所有关键字时,有时就可以发现其中的规律,利用这些规律可以构造hash函数。
hash表常见的解决冲突方法
除了在选用hash函数时尽量避免冲突外,在遇到冲突时还要想办法解决冲突。常见方法有以下几种:
1.开放定址法
(1)线性探测法
在遇到冲突时,继续往表的后面搜索,直到搜索到空位,函数是H(k)=(H(k)+i)%a,其中i是从1递增的,直到a-1或者搜索到空位。
(2)二次探测法
这种方法是在原来位置的两边交替地搜索,函数是H(k)=(H(k)+d)%a 其中d是次数的平方,为正或为负。
2.再散列法
出现冲突时,采用与原来不同的hash函数来求Hash地址,当然如果还找不到,就再用别的hash函数,知道搜到空位为止。
3.拉链法(链地址法)
采用类似于图的邻接链表的形式存储hash地址一样的关键字。与线性探测法比较就可以发现,其平均查找长度小于线性探测法,原因是在寻找目标的过程中,可能会查找到与原本hash地址不一样的元素,换句话说,线性探测法是在全表中查找,而拉链法构造的表在被查找的过程中是在由所有冲突的元素构成的局部中查找,这些元素原本的hash地址是相同的。