1. Hash表定义
a) 又可称哈希表、散列表或是杂凑表
b) 二分实用的查找技术,具有极高的查找效率
c) 冲突:关键字不同,但是Hash地址相同的现象。
对21,30,11三个数,利用k Mod 3,求他们的哈希地址:
21 % 3 = 0
30 % 3 = 0
11 % 3 = 2
2. Hash函数构造方法
a) 没有定式要求,根据实际情况,是否符合要求就可以。尽可能减少冲突就是好的构造方法。
b) 常用的构造方法:
i. 直接定址法:取关键字或关键字的某个线性函数值为哈希地址。即
H(key) = key 或 H(key) = a*key +b ;
ii. 除余法:用关键码除以表元素总数后得到的余数为存储地址,如上例。
iii. 基数转换法:将关键码看作是某个基数制上的整数,然后将其转换为另一基数制上的
数,如:21、30、11,可以把这3个数看成是8进制数,转成十进制有: 17、24、 9
iv. 平方取中法:先通过求关键字的平方值扩大相近数的差别,然后根据表长度取中
间的几位数作为散列函数值。又因为一个乘积的中间几位数和乘数的每一位都相
关,所以由此产生的散列地址较为均匀。
如:21、30、11进行平方取中法求哈希地址(取中间一位)
21*21=441 4
30*30=900 0
11*11=121 2
v. 折叠法:将关键码分成多段,左边的段向右折,右边的段向左折,然后将它们叠加
vi. 移位法:将关键码分为多段,左边的段右移,右边的段左移,然后将它们叠加;
vii. 机数法:选择一个随机函数,取关键码的随机函数值
3. 处理冲突方法:
a) 开放定址法:当冲突发生时,使用某种探查技术在散列中形成一个探序列。沿着序列查找,直到找到关键字或一个开发的地址(地址单元为空)。
i. 线性探查法:冲突后直接向下线性查找一个新的空间存放。
如:3,8,12,17,9,取m=10(存储空间为10),p=5,散列函数h=key % p
3 % 5 = 3 8 % 5 = 3 12 % 5 = 2
17 % 5 = 2 9 % 5 = 4
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 |
|
| 3 |
|
|
|
|
|
|
|
2 |
|
| 3 | 8 |
|
|
|
|
|
|
3 |
| 12 | 3 | 8 |
|
|
|
|
|
|
4 |
| 12 | 3 | 8 | 17 |
|
|
|
|
|
5 |
| 12 | 3 | 8 | 17 | 4 |
|
|
|
|
ii. 双散列函数法:
关键码(4,11,16,54),m=11 , p=7 , h=key % p ,
二次散列函数为:hi=(h(key)+key%(p-1))%p
*根据h和hi求出相应的hash地址
b) 拉链法:将散列表的每个结点增加一个指针字段,用于链接同义词的子表,链表中的结点都是
同义词。如:记录为(3,91,12,17,18),取p=5 , 散列函数h=key % p ;
0 |
|
|
|
| |
1 |
|
|
|
| |
2 | 12 |
| 17 | ^ | |
3 | 3 |
| 18 | ^ | |
4 | 9 | ^ |
|
|
4. 哈希表的查找
已知一个线性表(38,25,74,63,52,48),假定采用散列函数h(key)=key % 7 计算散列地址,并散列存储在散列表A[0,…,6]中,若采用线性探测方法解决冲突,则在该散列表上进行等概率成功查找的平均查找长度为:?
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 次数 |
1 |
|
|
| 38 |
|
|
| 1 |
2 |
|
|
| 38 | 25 |
|
| 1 |
3 |
|
|
| 38 | 25 | 74 |
| 2 |
4 | 63 |
|
| 38 | 25 | 74 |
| 1 |
5 | 63 |
|
| 38 | 25 | 74 | 52 | 4 |
6 | 63 | 48 |
| 38 | 25 | 74 | 52 | 3 |
所以平均查找长度:n =( 1+1+2+1+4+3) / 6 = 2 ;