- 什么是哈希表?
理想情况是希望不经过任何比较,一次存取便能得到所查记录,那就必须在记录的存储位置 f(k) 和它的关键字 k 之间建立一个确定的关系 f 。使每个关键字,通过f(k)找到对应的存储位置。因此不需要任何比较便能得到所查记录。为此,我们称这个对应关系 f 为哈希函数(Hash),按这个思想建立的表为哈希表。
哈希函数就像在新华字典查找一个字,按拼音或笔画(key) 先查到页数( f(key) 地址) ,再去对应页数找对应的字(记录)。
如果不是按这样来,那就需要从字典的第一个字开始比较,直到比较得到一个字与你要的字相等,这样也太麻烦了。
- 哈希碰撞/冲突
我们的理想是对于同一个key只有一个哈希地址与之对应。但现实不是这样的,可能不同的key,却可以得到相同的哈希地址,因为 f(key) 它只能保证你输入一个key,它能给你一个哈希地址。但是并不能保证 f(k1) != f(k2)。就像查字典,你并不能保证按不同的拼音查可以得到不同的页数,因为也可以得到相同的页数,就比如多音字。这一现象称为冲突/哈希碰撞。冲突只能尽可能地少,不能完全避免。
- 哈希表
用哈希函数 H(key) 将一组关键字映像到一个有限的连续的地址集上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表。这个过程称为哈希造表或散列,所得的储存位置称哈希地址或散列地址。所以哈希表也称散列表。
- 哈希函数的构造方法
直接定址法 H(key) = key 或 H(key) = a*key + b
数字分析法
平方取中法
折叠法
除留余数法 H(key) = key MOD p ,p <= m (m为哈希表长)
随机数法
一个好的哈希表取决于好的哈希函数,好的哈希函数取决于好的构造方法。这里不详细介绍构造方法了。
- 处理哈希碰撞的方法
1.开放定址法
H(i) = ( H(key) + ) MOD m ,【 i=1,2,...,k (k<= m-1) 】
H(key) 为哈希函数(发生碰撞时则使用H(i)) m为哈希表表长 为增量序列 MOD是取余
所以根据 增量序列 的不同表示,又分三种:
= 1,2,3,...,m-1 时,称线性探测再散列
=
,-
,
,-
,...,
时,称二次探测再散列
= 伪随机序列 时,称随机探测再散列
至于上面说的是啥意思,看一个例子:
2.再哈希法
H(i) = RH(key) ,i=1,2,...,k
R 和 H 均是不同的哈希函数,当H(key)产生的地址冲突时,用H(i)计算得到新的哈希地址,直到不发生冲突。
3.链地址法
将所有关键字为同义词的记录存储在同一线性链表中。看一个例子:
4.建立一个公共溢出区 不详细介绍了