哈希表支持的一种最有效的检索方法:散列.数组
因为计算哈希值和在数组中进行索引都只消耗固定时间,所以哈希表的最大亮点在于他是一种运行时间在常量级的检索方法.函数
哈希表主要有两种:编码
1.链式哈希表:将数据存储在桶中的哈希表,每一个桶里面都是一个链表,且链表的容量随着冲突的增大而增大.(换句话说就是若是有冲突,会在桶中的链表加上一个存储的值)spa
2.开地址哈希表:将数据存在表自己,而不是在桶中,他经过各类探查方法来避免冲突.索引
解决冲突:循环
无论在以上那种哈希表中,咱们的目标是尽量均匀的分配表中的元素.因此咱们必须选择正确和哈希函数.方法
在链式哈希表中,哈希函数能够表示为:链表
h(k)=x数据
通常来讲,大多数的散列方法都假设键值k为整数,因此,若是设置键值须要把传入的类型进行转换.时间
哈希函数可使用:
取余法:
h(k)= k mod m (其中k表示转换后的整数,m表示哈希表的桶数)
好比:有m=11个位置,k为25,获得桶的索引index=25%11=3,因此在bucket[index]的位置存入值.
通常来讲,须要避免m的值是2的幂,一般选择一个素数.
乘法:
h(k)= m(kA mod 1),
他将整数k乘以一个常数A(0<A<1),取结果的小数部分,而后乘以m取结果的整数部分.一般状况下,A取0.618,他是由√‾5减1除以2获得.
这个方法的有点是在取m得时候不须要啊那么慎重.
最后,若是仍是有冲突的元素在一个桶内,哈希表会用链式结构存储冲突元素.
开地址哈希表
因为元素放在表自己,没有链式结构存储冲突元素,哈希表须要其余方法解决冲突.
线性探查:开地址哈希表中一种简单的探查方法就是探查表中的连续槽位.
表示为:若是存在i(0<i<m-1)
h(k,i)= (h'(k)+i) mod m
其中h'(k)可使用上述的取余法.
大体步骤:
1.i=0,经过h'(k)找到一个位置,若是位置没有元素,就存储元素.
2.若是有元素,i+1来查看这个位置的下个位置是否有元素.
3.循环1,2步骤.
这个方法的主要缺点是元素不能均匀散列.
双散列:
最有效的探查的方法,就是经过计算两个辅助哈希函数哈希编码的和来获得哈希编码.
表示为:若是存在i(0<i<m-1)
h(k,i)=(h1(k)+ih2(k)) mod m
h1和h2是两个辅助哈希函数.
通常来讲:m的值取素数,而后令h1(k)= k mod m,h2(k)=1+(k mod m'),其中m'略小于m,通常取m'=m-1或者m-2;
这种方法的优势是能在表中探查并产生较好的元素分布,缺点是必须限制m的值.这样才能保证在一系列探查中访问表中全部槽以后才会再次探查任何槽.