数据结构之哈希表查找

数据结构之 哈希表查找

哈希表的基本概念
哈希表(Hash Table)又称散列表,是除顺序表存储结构、链接表存储结构和索引表存储结构之外的又一种存储线性表的存储结构。
  哈希表存储的基本思路是:
  

设要存储的对象个数为n,设置一个长度为m(m≥n)的连续内存单元,以线性表中每个对象的关键字ki(0≤i≤n-1)为自变量,通过一个称为哈希函数的函数h(ki),把ki映射为内存单元的地址(或称下标)h(ki),并把该对象存储在这个内存单元中。h(ki)也称为哈希地址(又称散列地址)。把构造的线性表存储结构称为哈希表。

  但是存在这样的问题,对于两个关键字ki和kj(i≠j),有ki≠kj(i≠j),但h(ki)=h(kj)。把这种现象叫做哈希冲突。
   通常把这种具有不同关键字而具有相同哈希地址的对象称做“同义词”,由同义词引起的冲突称作同义词冲突。

  在哈希表存储结构的存储中,同义词冲突是很难避免的,除非关键字的变化区间小于等于哈希地址的变化区间,而这种情况当关键字取值不连续时是非常浪费存储空间的。通常的实际情况是关键字的取值区间远大于哈希地址的变化区间。
  

归纳起来:
(1)哈希函数是一个映象,即将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可;
(2)由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即key1key2,而h(key1) = h(key2)。
(3)很难找到一个不产生冲突的哈希函数。一般情况下,只能选择恰当的哈希函数,使冲突尽可能少地产生。

哈希函数构造方法
构造哈希函数的目标是使得到的哈希地址尽可能均匀地分布在n个连续内存单元地址上,同时使计算过程尽可能简单以达到尽可能高的时间效率。

  • 直接定址法

直接定址法是以关键字k本身或关键字加上某个数值常量c作为哈希地址的方法。直接定址法的哈希函数h(k)为:
h(k)=k+c   这种哈希函数计算简单,并且不可能有冲突发生。当关键字的分布基本连续时,可用直接定址法的哈希函数;否则,若关键字分布不连续将造成内存单元的大量浪费。

  • 除留余数法

除留余数法是用关键字k除以某个不大于哈希表长度m的数p所得的余数作为哈希地址的方法。除留余数法的哈希函数h(k)为:
h(k)=k mod p (mod为求余运算,p≤m)
p最好是质数(素数)。

例如
假设哈希表长度m=13,采用除留余数法哈希函数建立如下关键字集合的哈希表:{16,74,60,43,54,90,46,31,29,88,77}。
解:n=11,m=13,除留余数法的哈希函数为:
  h(k)=k mod p
 p应为小于等于m的素数,假设p取值13。则有:
h(16)=3,h(74)=9,h(60)=8,h(43)=4,
h(54)=2,h(90)=12,h(46)=7,h(31)=5,
h(29)=3, h(88)=10,h(77)=12

注意:存在冲突。

哈希冲突在所难免
在哈希表中,虽然冲突很难避免,但发生冲突的可能性却有大有小。这主要与三个因素有关:

与装填因子有关

所谓装填因子α是指哈希表中已存入的元素数n与哈希地址空间大小m的比值,即α=n/m, α越小,冲突的可能性就越小;
α越大(最大可取1),冲突的可能性就越大,这很容易理解,因为α越小,哈希表中空闲单元的比例就越大,所以待插入元素同已插入的元素发生冲突的可能性就越小;反之,
α越大,哈希表中空闲单元的比例就越小,所以待插入元素同已插入的元素冲突的可能性就越大;另一方面,
α越小,存储空间的利用率就越低;反之,存储空间的利用率也就越高。为了既兼顾减少冲突的发生,又兼顾提高存储空间的利用率这两个方面,通常使最终的控制在0.6~0.9的范围内。

与所采用的哈希函数有关

若哈希函数选择得当,就可使哈希地址尽可能均匀地分布在哈希地址空间上,从而减少冲突的发生;否则,若哈希函数选择不当,就可能使哈希地址集中于某些区域,从而加大冲突的发生。

与解决冲突的哈希冲突函数有关

哈希冲突函数选择的好坏也将减少或增加发生冲突的可能性。

  • 如何解决哈希冲突?

开放定址法
开放定址法是一类以发生冲突的哈希地址为自变量,通过某种哈希冲突函数得到一个新的空闲的哈希地址的方法。

  1. 线性探测法。

    线性探测法是从发生冲突的地址(设为d)开始,依次探测d的下一个地址(当到达下标为m-1的哈希表表尾时,下一个探测的地址是表首地址0),直到找到一个空闲单元为止(当m≥n时一定能找到一个空闲单元)。线性探测法的数学递推描述公式为:
    d0=h(k)
    di=(di-1+1) mod m (1≤i≤m-1)

  2. 平方探测法

    设发生冲突的地址为d,则平方探测法的探测序列为:d±12,d±22,…。平方探测法的数学描述公式为:
    d0=h(k)
    di=(d0± i2) mod m (1≤i≤m-1)
    平方探测法是一种较好的处理冲突的方法,可以避免出现堆积问题。它的缺点是不能探测到哈希表上的所有单元,但至少能探测到一半单元。

例如:
采用除留余数法哈希函数建立如下关键字集合的哈希表:{16,74,60,43,54,90,46,31,29,88,77}。
除留余数法的哈希函数为:
   h(k)=k mod 13
对构造的哈希表采用线性探测法解决冲突。
解:h(16)=3,h(74)=9,h(60)=8,h(43)=4,
h(54)=2,h(90)=12,h(46)=7,h(31)=5,
h(29)=3 冲突
d0=3,d1=(3+1) mod 13=4 仍冲突
d2=(4+1) mod 13=5 仍冲突
d3=(5+1) mod 13=6
h(88)=10
h(77)=12 冲突
d0=12,d1=(12+1) mod 13=0
建立的哈希表ha[0..12]如下表所示
数据结构之哈希表查找_第1张图片

你可能感兴趣的:(ACM_数据结构,数据结构)