数组的特点是:寻址容易,插入和删除困难。
链表的特点是:寻址困难,插入和删除容易。
而哈希表综合两者的特性,寻址容易、插入和删除也很容易。
哈希表(Hash Table),也叫散列表,是根据关键码值(key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
记录的存放位置=f(关键字)
其中对应关系f称为散列函数,又称为hash函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表。而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换对应的数组下标,并定位到该空间获取value。
关键字(key)通过哈希函数得到哈希地址,而把对应的值(value)存放在哈希地址这个存储位置。而记录这整个key-value信息的表就是哈希表。
哈希冲突:两个关键字key1!=key2,但是key1和key2通过哈希函数得到存储位置(即哈希地址)是一样的。哈希冲突只能尽可能减少,是不能完全避免的。
均匀的哈希函数:若对于关键字集合中的任一个关键字,经过哈希函数映射到地址集合的任何一个地址的概率都是相等的,则称此类哈希函数为均匀的哈希函数,从而减少哈希冲突。
判断一个哈希函数的优劣:
- 是否将关键字均匀映射到哈希空间上
- 有无好的解决冲突的方法
- 计算哈希函数是否简单高效
常见构建哈希函数的六个方法:
- 直接定值法
- 数字分析法
- 平方取中法
- 折叠法
- 除留余数法
- 随机数法
1)直接定值法
直接定值法的哈希函数就是一个一次函数,取关键字和关键字的某个线性函数值为哈希地址。

2)数字分析法
如果关键字由多位字符或者数字组成,就可以考虑抽取其中的2位或者多位作为该关键字对应的哈希地址,在取法上尽量选择变化多的位,避免冲突发生。
3)平方取中法
平方取中法是对关键字做平方操作,取中间几位作为哈希地址(此方法是比较常用的构造函数的方法)。
4)折叠法
折叠法是将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。关键字位数很多,且关键字每一位上数字分布大致均匀。
5)残留余数法
若已知整个哈希表的最大长度m,可以取一个不大于m的数p,然后对关键字key做取余运算,即f(key)=key%p。也是最常用的。
6)随机数法
随机数法既是取关键字的一个随机函数值作为它的哈希地址,适用于关键之长度不一的情况。如f(key)=random(key)。
常见的解决哈希冲突的方法
- 开放定址法
- 再哈希法
- 链地址法(拉链法、位桶法)
- 公共溢出区
1)开放定址法

f(key)是哈希函数,m是哈希表的长度,d是一个增量。
- 线性探测法(线性探测再散列)
d = 1,2,3,4,5…,m-1 - 二次探测法(二次探测再散列)
d=1^2,-1^2,2^2,-2^2…k^2,-k^2(k<=m-1) - 伪随机数探测法(伪随机探测再散列)
d=伪随机序列

2)链地址法(拉链法,位桶法)
将产生冲突的关键字的数据存储在冲突哈希地址的一个线性链表中。
f(key)=key mod 13

3)再哈希
如果产生了冲突,则使用另一个哈希函数来计算该关键字的地址,直到不发生冲突。此方法会增加计算时间。
4)公共溢出区
建立一个公共溢出区也是解决冲突的其中一个方法,基本步骤是通过建立两张表,一张为基本表,另一张为溢出表。基本存储没有发生冲突的数据,溢出表存放发生冲突的数据。不管关键字通过哈希函数得到的哈希地址是什么,只要发生了冲突,都存放在溢出表。
posted on
浙公网安备 33010602011771号