基本概念
哈希表(hash table):又称散列表,其基本思路是,设要存储的元素个数是n,设置一个长度为m的连续存储单元,以每个元素的关键字作为自变量,通过哈希函数(h(k))把k映射到一个内存单元,并把该元素存在这个内存单元中,把像这样构造的线性表存储结构称为哈希表。
哈希冲突(hash collisions):在构建哈希表时,出现两个不同关键词对应相同的哈希值,这种现象称作哈希冲突。
装填因子(loading factor):设哈希表空间大小为n,填入表中元素个数为m,则$α=/frac{m}{n}$为哈希表的装填因子。
哈希查找两项基本工作:
- 计算位置:构造哈希函数确定关键词的位置
- 解决冲突:应用某种策略解决多个关键词位置相同的问题
这种查找的时间复杂度几乎是常量O(1),即查找时间与问题规模无关。
哈希函数的构造
一个好的哈希函数:
- 计算简单,以便提高转换速度
- 关键词对应地空间分布均匀,以尽量减少冲突
直接定址法
是以关键字k加上某个常量c作为哈希地址的方法,其哈希函数为:h(k)=k+c
特点:哈希函数计算简单。当关键字分布基本连续时,可以用直接定址法;否则,将造成内存单元大量浪费
除留余数法
是用关键字k除以整数p所得的余数作为哈希地址,表示为h(k)=k mod p
特点:计算比较简单,适用范围广,是最经常使用的一种哈希函数。
这种方法的关键是选好p,使得每个关键字经转换后映射到哈希表任意地址的概率相等。理论表明,p取不大于表长的素数时效果最好
数字分析法
是指提取关键字中取值较均匀的数字作为哈希地址
特点:它适用于所有关键字已知的情况,需要对关键字每一位的取值分布情况加以分析。
其它构造整数关键字的哈希函数还有平方取中法、折叠法、随机数法等。
哈希冲突的解决方法
开放定址法
线性探测法
是指从发生冲突的地方开始,依次探测下一个地址(表尾的下一个地址是表头),直到找到一个空闲的单元为止。
表示为:d0=h(k) di=((di-1+1)) mod size
特点:操作简单。但有一个重大的缺陷是容易产生聚集现象,当一个发生冲突,后面紧接着的单元都会由于前面的堆积发生冲突。
平方探测法
是指发生冲突时以±i2 进行探测,公式为:d0=h(k) di=((d0 ± i2)) mod size
特点:是一种较好的处理冲突的方法,其缺点是不一定能探测到哈希表上的所有单元,但至少能探测到一半单元。
理论表明,哈希表的长度为4k+3(k为整数)形式的素数,平方探测法可以探测到整个哈希表空间。
其它方法还有伪随机序列法、双哈希函数法等
拉链法
是指将所有哈希值相同的关键字用单链表链接起来。
在这种方法中,哈希表的每个单元存放的不再是元素本身,而是一个个单链表的头结点。
与开放定址法比较:
- 处理冲突简单,无堆积现象,因此平均查找长度较短
- 由于单链表的结点是动态申请,适合元素规模未知的情况
- 开放地址法为了减少冲突要求装填因子较小,故当数据规模较大时浪费空间;拉链法节省空间
- 用拉链法构造的哈希表中,删除结点比较简单
哈希表的性能分析
用平均查找长度(ASL)来度量查找表的查找效率:成功、不成功
哈希表的性能就是看比较次数,而比较次数取决于冲突的多少,影响冲突的因素:
- 哈希函数是否均匀
- 处理冲突的方法
- 装填因子α
我们这里只考虑后两种因素,主要是一些理论上的结果
线性探测法
可以证明,线性探测法的期望探测次数为:
当α=0.5时,ASLu=2.5次,ASLs=1.5次。
平方探测法
可以证明,平方探测法的期望探测次数为:
当α=0.5时,ASLu=2次,ASLs=1.39次
拉链法
把所有单链表的平均长度定义成装填因子α,α有可能超过1,可以证明,其平均期望探测次数p为:
当α=1时,ASLu=1.37次,ASLs=1.5次
总结
- 选取合适的哈希函数h(key),查找效率的期望是O(1)
- 以较小的α为前提,实质是以空间换时间
- 哈希表对关键词是随机存储的,不便顺序查找
- 不适合范围查找、最大最小值查找
参考链接:中国大学mooc 陈越、何钦铭 数据结构
来源:https://www.cnblogs.com/lfri/p/10134429.html