【查找】哈希(散列)查找
1. 基本概念
-
哈希(散列)函数:散列函数是将关键字映射为表中地址的函数,记为Hash(key)= Addr
-
冲突: 由于散列函数可能将不同关键字映射到同一地址,这种情况叫做冲突。
我们希望尽量减少这种冲突,所以需要寻找好的散列函数;同时,冲突是不可避免的,所以还需要设计解决冲突的方法。
-
同义词:映射到同一地址的不同关键字称为同义词。
-
哈希(散列)表
根据关键字直接进行访问的数据结构
2. 哈希(散列)函数的构造方法
- 直接定址法
H(key) = key # 或 H(key) = a * key + b
1,2,3,4,5,6,7 直接存储[1,2,3,4,5,6,7]
或
1,2,3,4,5,6,7 直接存储[3001,3002,3003,3004,3005,3006,3007]
优点:不会产生冲突
缺点:当关键字不连续的时候,空位会造成空间的浪费
- 除留取余法
H(key) = key % p # 对于表长为m的散列表,选取<=m且最大的质数作为p,以此来减少冲突
- 数字分析法
通过对所需存储关键字的特定进行分析,设计出好的哈希函数H(key) - 平方取中法
先对关键字做平方运算,然后对结果取中间的值作为映射地址
例如:11,12,13
平方结果 121 144 169
映射地址 2 4 6
3. 解决冲突的方法
3.1 开放定址法
Hi = ( H(key) + di ) % m
其中,H(key)为哈希函数,di表示第i次的增量,m为表长
开放指的是对空闲地址对同义词和非同义词都进行开放
- 线性探测法
增量序列di = 0,1,2,3,…,k - 平方探测法
增量序列di = 02,12,-12,22,-22,…,k2,-k2 - 双散列法
di = i * H2(key) - 伪随机序列法
给定一个随机序列di
3.2 链地址法
将同义词用链表进行保存
4. 查找过程
5. 性能分析
散列表
H(key) = key % 13,线性探测法处理冲突
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
14 | 01 | 68 | 27 | 55 | 19 | 20 | 84 | 79 | 23 | 11 | 10 |
假设当前关键字与比较次数如下
关键次数 | 14 | 01 | 68 | 27 | 55 | 19 | 20 | 84 | 79 | 23 | 11 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
比较次数 | 1 | 2 | 1 | 4 | 3 | 1 | 1 | 3 | 9 | 1 | 1 | 3 |
- 查找成功的平均查找长度ASL
ASL = ( 1 * 6 + 2 + 3 * 3 + 4 + 9 )/ 12 = 5.5 - 查找失败的平均查找长度ASL
由于哈希函数H(key) 只能得到0~12的数,所以只需要计算从这13个地址往后查找到空的次数就行了
ASL = (1 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2)/ 13 = 7 - 装填因子α
α = n / m = 12 / 16 = 0.75
其中n为记录数,m为散列表长度(是15+1,不是15)
由查找过程可见
1)由于冲突的产生,使得哈希表的查找需要对表中给定值与待查找的关键字进行对比,所以仍需要以平均查找长度作为查找效率的衡量标准
2)哈希表的查找效率取决于三个因素:哈希函数、处理冲突的方法、装填因子α