数据结构_散列表 Hash Tables

散列表定义

散列表,又称哈希表,hash表。散列表是一种特殊的数据结构,它同数组、链表以及二叉排序树等相比较有很明显的区别,它能

够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找。这个源于散列表设计的特殊性,它采用

了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。
 

设计思想

Hash表采用一个映射函数 f : key —> address 将关键字映射到该记录在表中的存储位置,从而在想要查找该记录时,可以直接根

据关键字和映射关系计算出该记录在表中的存储位置,通常情况下,这种映射关系称作为Hash函数,而通过Hash函数和关键字

计算出来的存储位置(注意这里的存储位置只是表中的存储位置,并不是实际的物理地址)称作为Hash地址。
 

HASH函数

  • 直接定址法 

取关键字或者关键字的某个线性函数为Hash地址,即Hash(key)=a*key+b

  • 除留余数法 

如果知道Hash表的最大长度为m,可以取不大于m的最大质数p,然后对关键字进行取余运算,Hash(key)=key%p。 
在这里p的选取非常关键,p选择的好的话,能够最大程度地减少冲突,p一般取不大于m的最大质数。

  • 平方取中法 

对关键字进行平方运算,然后取结果的中间几位作为Hash地址。假如有以下关键字序列{421,423,436},平方之后的结果为{177241,178929,190096},那么可以取{72,89,00}作为Hash地址。

  • 折叠法 

将关键字拆分成几部分,然后将这几部分组合在一起,以特定的方式进行转化形成Hash地址。假如知道图书的ISBN号为8903-241-23,可以将Hash(key)=89+03+24+12+3作为Hash地址。

冲突解决

无论利用上述哪种hash函数计算hash地址,难免会产生不同元素的hash地址一样,那么这样就产生了冲突,那么如何避免冲突

是一件很关键的事。下面有两种方式解决冲突:开放定址法与分离链接法(链地址法)。由于篇幅问题,这篇博文主要介绍开放

定址法

  • 开放定址法

当一个关键字和另一个关键字发生冲突时,使用某种探测技术在Hash表中形成一个探测序列,然后沿着这个探测序列依次查找下

去,当碰到一个空的单元时,则插入其中。基本公式为:hash(key) = (hash(key)+di)mod TableSize。其中di为增量序列,

TableSize为表长。根据di的不同我们又可以分为线性探测,平方(二次)探测,双散列探测。 

  1. 线性探测 

以增量序列 1,2,……,(TableSize -1)循环试探下一个存储地址,即di = i。如果table[index+di]为空则进行插入,反之试探下一个增量。但是线性探测也有弊端,就是会造成元素聚集现象,降低查找效率。
è¿éåå¾çæè¿°

特别对于开放定址法的删除操作,不能简单的进行物理删除,因为对于同义词来说,这个地址可能在其查找路径上,若物理删除的话,会中断查找路径,故只能设置删除标志。

  1. 平方探测 

以增量序列1,-1,4,-4…且q ≤ TableSize/2 循环试探下一个存储地址。

  1. 双散列探测 

di 为i*h2(key),h2(key)是另一个散列函数。探测序列成:h2(key),2h2(key),3h2(key),……。对任意的key,h2(key) ≠ 0 !探测序列还应该保证所有的散列存储单元都应该能够被探测到。选择以下形式有良好的效果: 
h2(key) = p - (key mod p) 
其中:p < TableSize,p、TableSize都是素数。
 

原文:https://blog.csdn.net/qq_30091945/article/details/78044445

猜你喜欢

转载自blog.csdn.net/weixin_38134491/article/details/84787158
今日推荐