4.哈希表
1.哈希表的基本概念
哈希表适合用于储存一些关键字和存储地址存在某种函数关系的数据。
储存地址=h(key);
这样储存元素的数据结构就叫做哈希表。
2.哈希表中的一些概念
1.哈希函数和哈希地址
假设存在m个储存空间,我们想要储存n个对象。
那么哈希函数h(k)就是把关键字为ki的对象储存在相应的哈希地址中。
此时的哈希表就是长度为m的(m<=n)的内存单元。
2.哈希冲突
对于两个关键字ki和kj(i!=j),并且ki!=kj,但是h(ki)=h(kj)的现象兼做哈希冲突,也叫做同义词冲突。
在哈希表的储存结构中,哈希冲突是很难避免的。
3.哈希表的设计
哈希表设计是为了解决哈希冲突,但是哈希冲突很难避免。
设计主要和三个因素有关:
1.装填因子:装填因子a=存在的记录个数/哈希表的大小,也就是n/m,其中a越小,冲突的可能性越小,反之。通常装填因子在0.6-0.9之间。
2.哈希函数:一个好的哈希函数可以有效避免冲突的产生。
3.解决冲突的方法:既然哈希冲突难以避免,我们就需要设计一个解决冲突的方法。
由于装填因子是已知的,所以我们重点在哈希函数和解决方法上。
4.哈希函数的构造方法
1.直接定址法
直接定址法就是以关键字k本身或者加上某个常数作为哈希地址的方法。
h(k)=k+c
2.除留余数法
除留余数法的哈希函数:
h(k)=k mod p (mod 为求余运算,p<=m,让算出来的地址在m个内存单元中)
p最好是素数(质数)。这样可以减少哈希冲突。
3.数字分析法
主要是把大范围的关键字转化为小返回的。
例如:2378565,我们就将最后两位65作为哈希地址。
5.哈希冲突的解决方法
1.开放定址法
开发定址法:冲突时找一个新的空闲的哈希地址
就像晚到电影院发现自己的座位被坐了,我们找那些没人坐的位置。
开发定址法又有以下方法:
1.线性探查法
d0=h(k) di=(d(i-1)+1)mod m
i在1到m-1中 闭区间。
这种方法容易产生非同义词冲突:哈希函数值不相同的两个关键字争夺同一个后继哈希地址,也就是堆积现象
2.平方探查法
d0=h(k)
di=(d0 ±i 的平方)mod m
查找的位置依次是:d0 d0+1 d0-1 d0+4 d0-4
平方探查法可以避免出现堆积现象,但是不能探查到哈希表上的所欲的位置,至少一半。
2.拉链法
拉链法就是把所有同义词用单链表连接起来的方法。
像JAVA中的HASHMAP就是采用的拉链法解决的冲突。