1.哈希表
哈希表(亦称为散列表)是一种根据关键码寻找值的数据映射结构。哈希表设计了映射关系f(key)=address,根据key计算存储地址address,以下图为例:
若想寻找余罪,可利用哈希函数:f(余罪)=s,所以可以在O(1)的时间内访问任意位置。
2.哈希冲突
哈希函数的映射可能会出现碰撞,即有多个元素被映射到同一个位置,出现哈希冲突,它与哈希函数的设计是正相关的,当哈希函数的随机性越大,产生哈希冲突的可能性越小。解决哈希冲突的方法主要有:
- 链接法
- 开放寻址法
2.1 链接法
链接法是将映射到同一个位置(称为槽、slot)的元素做成链表,假设元素个数为n,槽的个数为m,则定义装载因子α=n/m,也就是平均每个链表中元素的平均数量,在最坏情况下,哈希函数f()可能将所有的key映射到同一个槽中,则哈希表的查找时间为查找长度为n的链表,需要花费O(n)。
此时哈希函数的选择应遵循简单均匀散列假设:任何给定元素会等可能的映射到m个槽中的任意一个,并且与其他元素的位置所在无关。
则对于链接法解决哈希冲突的哈希表,一次成功查找和不成功的平均时间均为θ(1+α),其中θ(1)为计算哈希值和访问槽的时间。一般来说,当α=O(1)或n=O(m),即散列表的个数与元素个数成正比,查找哈希表的时间为O(1)。
此时哈希函数的构造:
2.1.1 除法散列法
f(key)=key mod m, 即为k/m取余数。注意不要选择过下的m,最好值为质数,不接近2的幂(此时哈希不会考虑到k的所有位)。
2.2.2 乘法散列法
f(key)=floor(m(kA mod 1)),0<A<1, floor为下取整,mod1为取小数部分。
2.2 开放寻址法
开放寻址法即系统的探查哈希表,知道找到一个空槽,此时α<1。该方法需要连续的探查哈希表,探查的顺序为probe sequence,写作:
<f(key,0),f(key,1),...,f(key,m-1)>,探查的过程为,初始化i=0,计算f(k,i),若该位置为空槽,将元素放入,否则I++,继续探查。
哈希函数的构造:
2.2.1 线性探查
f(key,i)=(f(key,0)+i) mod m,会遇到群集问题,即哈希表的某区间全部被占满。
2.2.2 二次哈希
f(key,i)=(f_1(key)+C*f_2(key)) mod m,以两种不同方式依赖于key,f_2(key)的值应与m大小互为素数,可以通过m取2的幂,或者m取素数,f_2(k)小于m。
2.2.3 完全哈希
先hash一次,找到空槽,再hash一次,找到二级hash表中的槽的位置,为保证二级hash表不冲突,需要让每个一级hash中槽中的二级hash表的大小为在这个槽中key的平方。
REFERENCE:
http://www.yixieshi.com/95421.html
算法导论(原书第三版)