散列表的查找
基本思想
记录的存储位置与关键字之间存在关系
对应关系:hash函数
散列表的术语
- 散列方法(杂凑法):选取某个函数按关键字计算元素的存储位置,并按此存放;查找时,由同一个函数对定值k计算地址,将k与地址单元中元素关键码进行对比,确定查找是否成功。
- 散列函数:散列方法中使用的转换函数
- 散列表:按上述思想构造的表
- 冲突:不同的关键码映射到同一个散列地址
- 同义词:具有相同函数值的多个关键字
冲突是不可能避免的,只能尽量减少
散列函数的构造方法
直接定址法
以关键码key的某个线性函数值为散列地址,不会产生冲突
Hash(key) = a*key + b
缺点:占用连续地址空间,空间效率低
除数留余法
Hash(key) = key mod p
设表长为m,取 p <= m 且为质数
处理冲突的方法
开放地址法
有冲突时就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到
线性探测法
Hi = (Hash(key)+di) mod m 1<=i<=m
m为散列表长度,di为增量序列1,2,…m-1,且di = i
一旦冲突就找下一个地址,直到找到空地址存入
例:关键码集为{47,7,29,11,16,92,22,8,3},散列函数为Hash(key) = key mod 11
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
11 | 22 | 47 | 92 | 16 | 3 | 7 | 28 | 8 | ||
1 | 2 | 1 | 1 | 1 | 4 | 1 | 2 | 2 |
29 22 8 3 在散列地址上均有冲突
平均查找长度ASL = (1+2+1+1+1+4+1+2+2) / 9 = 1.67
二次探测法
Hi = (Hash(key)+di) mod m 1<=i<=m
di为增量序列 12, -12,22 -22 …
例:关键码集为{47,7,29,11,16,92,22,8,3},散列函数为Hash(key) = key mod 11
0 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
---|---|---|---|---|---|---|---|---|---|---|
11 | 22 | 3 | 47 | 92 | 16 | 7 | 29 | 8 | ||
1 | 2 | 1 | 1 | 1 | 2 | 2 |
平均查找长度ASL = (1+2+3+1+1+1+1+2+2) / 9 = 1.56
链地址法
相同散列地址的记录链成一单链表
m个散列地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构
例:一组关键字为{19,14,23,1,68,20,84,27,55,11,10,79}
散列函数为Hash(key) = key mod 11
优点:非同义词不会冲突;链表上结点动态申请,更适合表长不确定的情况