哈希表中的查找

非 Y 不嫁゛ 提交于 2020-02-23 10:24:12

基本概念

哈希表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  陈越、何钦铭 数据结构

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!