查找——散列表(哈希表)的查找

前面的文章介绍了线性表及树表的查找算法:

查找的基本概念,线性表的顺序查找

线性表的折半查找与分块查找

查找——树表之二叉排序树

查找—树表之平衡二叉树

这篇文章则介绍散列表(即哈希表)的查找方法。

一,哈希表的构造

基本概念

优点:查找速度极快O(1),查找效率与元素个数n无关。

例1:

若将学生信息按如下方式存入计算机,如:

2001011810201的所有信息存入V[01]单元;

2001011810202的所有信息存入V[02]单元;

……

              将2001011810231的所有信息存入V[31]单元 

查找2001011810216的信息,可直接访问V[16]

例2:

        数据元素序列(14233992511),若规定每个元素k的存储地址Hk)=k,请画出存储结构图。

如何进行哈希表的查找?

        根据哈希函数Hk)=k

        查找key=9,则访问H(9)=9号地址,若内容为9则成功; 

        若查不到,则返回一个特殊值,如空指针或空记录 

我们需要知道以下概念: 

哈希方法(杂凑法)

选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;

查找时,由同一个函数对给定值k计算地址,k与地址单元中元素关键码进行比,确定查找是否成功。

哈希函数(杂凑函数)哈希方法中使用的转换函数

哈希表(杂凑表)按上述思想构造的表。

冲 突:不同的关键码映射到同一个哈希地址 。key1 !=key2H(key1)=H(key2)

同义词:具有相同函数值的两个关键字。

具体什么是冲突呢?我们来看一个例子:

冲突是不可避免的,那么我们如何才能减少冲突?

(1)构造好的哈希函数

(2)制定一个好的解决冲突方案

构造好的哈希函数

        (a)所选函数尽可能简单,以便提高转换速度;

        (b)所选函数对关键码计算出的地址,应在散列地址集中致均匀分布,以减少空间浪费。

构造好的哈希函数,我们需要考虑以下因素:

根据元素集合的特性构造

 要求一:地址空间尽量小

 要求二:均匀

则有以下方法:

1.直接定址法   2.数字分析法  3.平方取中法  4.折叠法  5.除留余数法  6.随机数法

1. 直接定址法

Hash(key) = a·key + b    (ab为常数)

优点:以关键码key的某个线性函数值为哈希地址,不会产生冲突。

缺点:要占用连续地址空间,空间效率低。

例: {100300500700800900},哈希函数Hash(key)=key/100

 2.除留余数法

Hash(key)=key  mod  p    (p是一个整数)

通过计算出散列表中元素除以7得到的余数作为存储地址的位置

如果两个数的余数一样时,就出现了冲突,那么如何处理冲突呢?

处理冲突的两种方法:

1.开放地址法(开地址法)

        基本思想:有冲突时就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。

A.线性探测法

Hi=(Hash(key)+di) mod m       ( 1≤i < m )

其中:m为哈希表长度

di 为增量序列 1,2,…m-1,且di=i

一旦冲突,就找下一个空地址存入旦冲突,就找下一个空地址存入 

例:

关键码集为 {477291116922283}

设:哈希表表长为m=11

        哈希函数为Hash(key)=key mod 11    

我们可以得到用线性探测法处理冲突的过程: 

 线性探测法的优点:只要哈希表未被填满,保证能找到一个空地址单元存放有冲突的元素。

                       缺点:可能使第i个哈希地址的同义词存入第i+1个地址,这样本应存入第i+1个哈希地址的元素变成了第i+2个哈希地址的同义词,……,产生“聚集”现象,降低查找效率。

为了解决这种现象,我们引入了另一种方法处理冲突:

B.二次探测法

Hi=(Hash(key)±di) mod m

其中:m为哈希表长度,m要求是某个4k+3的质数;

      di为增量序列 12,-12,22,-22,…,q2

例:

关键码集为 {477291116922283}

设:    哈希函数为Hash(key)=key mod 11   

Hash(3)=3,哈希地址冲突,由

H1=(Hash(3)+1*1) mod 11=4,仍然冲突;

H2=(Hash(3)+(-1)*(-1)) mod 11=2,找到空的哈希地址,存入。

 C.伪随机探测法

Hi=(Hash(key)+di) mod m       ( 1≤i < m )

其中:m为哈希表长度

di 为随机数

 2.链地址法(拉链法)

基本思想:相同哈希地址的记录链成一单链表,m个哈希地址就设m个单链表,然后用用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。

链地址法建立哈希表步骤 :

step1 取数据元素的关键字key,计算其哈希地址。若该地址对应的链表为空,则将该元素插入此链表;否则执行step2解决冲突。

step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若该地址对应的链表为不为空,则利用链表的前插法或后插法将该元素插入此链表。

链地址法的优点:

同义词不会冲突,无“聚集”现象

链表上结点空间动态申请,更适合于表长不确定的情况

二,哈希表的查找

例:

已知一组关键字(19,14,23,1,68,20,84,27,55,11,10,79)

  哈希函数为:H(key)=key MOD 13, 哈希表长为m=16

  设每个记录的查找概率相等

(1)  用线性探测再散列处理冲突,即Hi=(H(key)+di) MOD m

ASL=(1*6+2+3*3+4+9)/12=2.5

(2)  用链地址法处理冲突

关键字(19,14,23,1,68,20,84,27,55,11,10,79)

ASL=(1*6+2*4+3+4)/12=1.75

对于这个例子,我们思考是用无序表查找还是有序表折半查找?ASL又如何?

从哈希表的查找效率分析

使用平均查找长度ASL来衡量查找算法,ASL取决于

哈希函数

处理冲突的方法

哈希表的装填因子

a 越大,表中记录数越多,说明表装得越满,发生冲突的可能性就越大,查找时比较次数就越多。

我们可以得到以下结论:

哈希表技术具有很好的平均性能,优于传统技术 

链地址法优于开地址法

除留余数法优于其它哈希函数

  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值