数据结构--哈希表

哈希表查找

本节提要

  1. 哈希查找的概念。
  2. 哈希函数的构造方法。
  3. 处理冲突的方法。
  4. 哈希查找的过程。

哈希存储、查找的概念

哈希存储是一种由关键字自身决定其存储位置存储结构。通过哈希函数 ( H(k) ) 计算关键字 ( k ) 的存储地址。理想情况下,哈希查找的时间复杂度为 ( O(1) )。
H(k) 称为哈希函数。这种存储结构称为哈希表。

哈希函数的特点

  • Hash( 输入 ) = 输出
  • 输入:可为不固定长度的值。
  • 输出:固定长度的值。
  • 单向不可逆:无法从输出值反推出输入值。
  • 输出值能反映输入值的大部分特征。

哈希函数的应用

  1. 验证用户输入密码是否正确。
  2. 判断文件、消息等数据的完整性。
  3. 分布式应用,如BT下载。
  4. 比特币、区块链。

哈希函数示例

已知地址区间为:0~6,关键字序列为:{20, 30, 70, 12, 18}。哈希函数为 ( h(k) = k % 7 ),则构造的哈希表如下:

地址  0  1  2  3  4  5  6

关键字 18 20 30 70 12

在这里插入图片描述

在这里插入图片描述

哈希函数问题

如果继续添加新的关键字14,会出现冲突。冲突是指关键字不同,但哈希函数值相同。构造哈希表时需要设计良好的哈希函数与处理冲突的方法。
在这里插入图片描述
在这里插入图片描述
冲突:关键字不同,哈希函数值相同。冲突的关键字称为同义词。
冲突无法避免,因此构造哈希表时需要同时设计良好的哈希函数与处理冲突的方法

哈希表设计方法

哈希表设计主要需要解决哈希冲突。实际中哈希冲突是难以避免的,主要与3个因素有关:

  • 与装填因子有关。
    装填因子α=存储的记录个数/哈希表的大小=n/m  α越小,冲突的可能性就越小; α越大(最大可取1),冲突的可能性就越大。通常使最终的控制在0.6~0.9的范围内。

  • 与所采用的哈希函数有关。
    好的哈希函数会减少冲突的发生;不好的哈希函数会增加冲突的发生。

  • 与解决冲突方法有关。
    好的哈希冲突解决方法会减少冲突的发生。

  • 哈希表设计的重点:

  • 尽可能设计好的哈希函数,尽可能使哈希地址出现在表中任意位置的概率均等,从而减少冲突。

  • 设计解决冲突的方法。

  1. 哈希函数构造方法

    • 直接定址法
    • 除留余数法
    • 数字分析法
    • 平方取中法
    • 折叠移位法
  2. 解决冲突的方法

    • 开放定址法
    • 线性探查法
    • 平方探查法
    • 双散列函数探查法
    • 链地址法

直接定址法

取关键字本身或关键字的某个线性函数值作为哈希地址。例如,( h(key) = key ) 或 ( h(key) = a*key + b )。
取关键字本身或关键字的某个线性函数值作为哈希地址。

h(key)=key 或 h(key)=a*key+b (a 和 b 均为常数)
  示例:利用哈希表保存从2000年到2019年每年出生的人数。关键字k为年份,共有20年,地址区间为0~19。
  用直接定址法设置哈希函数为:
h(k)=k-2000
哈希表如下:在这里插入图片描述
适用场景:关键字和地址一一对应,不会产生冲突。
只适用于关键字基本连续的情况。
如关键字序列为{1, 45, 99},哈希函数为h(k)=k,则地址区间为(1~99),但只存放3个关键字,造成空间严重浪费。
在这里插入图片描述

除留余数法

以关键字被某个整数 ( m ) 除后所得余数作为哈希地址。( h(k) = k % m ),其中 ( m ) 应小于或等于表长。以关键字被某个整数m除后所得余数作为哈希地址。
h(k) = k % m (m<=表长)
余数区间为 (0~m-1),与哈希表地址区间一致。
m为质数(素数)时,冲突的可能性相对较少。
除留余数法为常用方法。
示例:
已知连续的地址区间为0~6,
关键字k的序列为{20,30,70,12,18},
哈希函数为h(k)=k%7,则构造的哈希表为:
在这里插入图片描述

其中,k%7就是用除留余数法设计的哈希函数,7是一个等于表长的质数。

数字分析法

如果关键字的数位相同,且取值事先知道,则可对关键字进行分析,取其中分布均匀的若干位或它们的组合作为哈希地址。
如果可能出现的关键字的数位相同,且取值事先知道,则可对关键字进行分析,取其中“分布均匀”的若干位或它们的组合作为哈希地址。
示例:通过分析如下一组关键字可知:
关键字的第1,2,3位和第6位取值较集中,不宜作为哈希地址。
第4,5,7和8位取值较分散,可根据实际需要取其中的若干位作为哈希地址。
在这里插入图片描述

处理冲突的方法

  1. 开放定址法

    • 使用某种探查技术,在哈希表中形成一个探查序列,当冲突发生时,沿此序列查找空闲单元地址。
      h0 = h(k)
      hi = ( h0 + di ) % m ( 1 ≤ i ≤ m-1 )
      hi 为第 i 次冲突时探查的下一地址
    • 线性探查法:di = i 即依次为:1, 2, 3, …, m-1
    • 平方探查法: di = ±i2即依次为:+1, -1, +4, -4, …
    • 双哈希函数探查法:di = i * h2(k)
    • 示例:已知哈希表长13,地址区间0~12,关键字序列{15,59,22,34,20,35},哈希函数h(k)=k%13,采用线性探查法处理冲突,构造哈希表。
      h(15)=15%13=2,存至A[2]; h(59)=59%13=7,存至A[7]。
      h(22)=22%13=9,存至A[9]; h(34)=34%13=8,存至A[8]。
      h(20)=20%13=7,存至A[7]。 冲突;
      h0=7; h1=(h0+1)%13=8,仍冲突;
      h2=(h0+2)%13=9,仍冲突;h3=(h0+3)%13=10,存至A[10];
      h(35)=35%13=9,冲突;(同义词引起的冲突)
      h0=9; h1=(h0+1)%13=10,仍冲突(非同义词);
      h2=(h0+2)%13=11,存至A[11];
      在这里插入图片描述
      h(20)=20%13=7
      h(35)=35%13=9
      上例中,35与20的哈希地址不同,但争夺同一个后继地址。这种现象称为聚集。
      聚集将造成不是同义词的元素也处在同一个探查序列中,从而增加了查找时间。
      如发现聚集较严重,可改用平方探查法。
  2. 链地址法

    • 哈希地址相同的元素放置于一个单链表,链表的头指针放置于对应的哈希地址处。
    • 在这里插入图片描述
      在这里插入图片描述

哈希表的查找

  1. 开放定址法
    • 计算待查找元素 ( k ) 的哈希地址 ( H(k) )。
    • 如果该位置没有元素,则查找失败。
    • 该位置有元素,与 ( k ) 相比较:
      • 如果相等,查找成功。
      • 如果不相等,则按建表时设定的冲突处理方法找下一个地址。
  • 回到步骤 2 和 3,继续查找。如果探查序列上的全部元素都比较完后,仍未找到,则查找失败。
  1. 链地址法
    • 计算待查找元素 ( k ) 的哈希地址 ( H(k) )。
    • 如果该位置头指针为空,则查找失败。
    • 头指针不空,对应链表中的元素依次与 ( k ) 相比较:
      • 如果相等,查找成功。
      • 如果对应链表的全部元素都比较完后,仍未找到,则查找失败。

练习

已知哈希表地址区间为 0~10,给定关键字序列 {20, 30, 70, 15, 8, 12, 18, 63, 19}。哈希函数为 ( h(k) = k % 11 ),分别采用线性探查法和链地址法处理冲突,构造哈希表。

线性探查法
- ( h(20) = 20 % 11 = 9 );( h(30) = 30 % 11 = 8 );( h(70) = 70 % 11 = 4 );( h(15) = 15 % 11 = 4 ),冲突;( h_1 = (4 + 1) % 11 = 5 );( h(8) = 8 % 11 = 8 ),冲突;( h_1 = (8 + 1) % 11 = 9 ),冲突;( h_2 = (8 + 2) % 11 = 10 );( h(12) = 12 % 11 = 1 );( h(18) = 18 % 11 = 7 );( h(63) = 63 % 11 = 8 ),冲突;( h_0 = 8 );( h_1 = (8 + 1) % 11 = 9 ),冲突;( h_2 = (8 + 2) % 11 = 10 ),冲突;( h_3 = (8 + 3) % 11 = 0 );( h(19) = 19 % 11 = 8 ),冲突;( h_0 = 8 );( h_1 = (8 + 1) % 11 = 9 ),冲突;( h_2 = (8 + 2) % 11 = 10 ),冲突;( h_3 = (8 + 3) % 11 = 0 ),冲突;( h_4 = (8 + 4) % 11 = 1 ),冲突;( h_5 = (8 + 5) % 11 = 2 )。
在这里插入图片描述
哈希表:在这里插入图片描述

链地址法

  • 在这里插入图片描述
    在这里插入图片描述

总结

  1. 哈希函数的特点以及构造方法。
  2. 冲突产生的原因以及处理冲突的方法。
  3. 哈希查找的方法。

练手题目

1.已知哈希函数为H(k)=k%11,线性探测法解决冲突,根据哈希表的状态图,完成下面问题,并写出过程及结果。
0 1 2 3 4 5 6 7 8 9 10
23 13 45 15 16 26 18 20 31

1)在上述哈希表的状态图中,空位置上标记空标志NULLFLAG,查找45;
0 1 2 3 4 5 6 7 8 9 10
NULLFLAG 23 13 45 15 16 26 18 NULLFLAG 20 31
H(45)=45%11=1,地址被占用,线性探查下一地址;
H1 =(H(45)+1)%11=2,占用;
H2 =(H(45)+2)%11=3,查找成功。

2)查找5,若5不存在,则将其插入;
H(5)=5%11=5,地址被占用,线性探查下一地址;
H1 =(H(5)+1)%11=6,占用;
H2 =(H(5)+2)%11=7,占用;
H3 =(H(5)+3)%11=8,空,查找失败。
0 1 2 3 4 5 6 7 8 9 10
NULLFLAG 23 13 45 15 16 26 18 5 20 31

3)查找26,若26存在,则将其删除,并在相应位置设置删除标志DELETEFLAG;
H(26)=26%11=4,地址被占用,线性探查下一地址;
H1 =(H(26)+1)%11=5,占用;
H2 =(H(26)+2)%11=6,查找成功。
0 1 2 3 4 5 6 7 8 9 10
NULLFLAG 23 13 45 15 16 DELETEFLAG 18 5 20 31

4)查找5,若5存在,则将其删除;
H(5)=5%11=5,地址被占用,线性探查下一地址;
H1 =(H(5)+1)%11=6,删除标志,继续探查;
H2 =(H(5)+2)%11=7,占用;
H3 =(H(5)+3)%11=8,查找成功
0 1 2 3 4 5 6 7 8 9 10
NULLFLAG 23 13 45 15 16 DELETEFLAG 18 DELETEFLAG 20 31

5)查找10,若10不存在,则将其插入;
H(10)=10%11=10,地址被占用,线性探查下一地址;
H1 =(H(10)+1)%11=0,空,查找失败。
0 1 2 3 4 5 6 7 8 9 10
10 23 13 45 15 16 DELETEFLAG 18 DELETEFLAG 20 31

6)查找27,若27不存在,则将其插入;
H(27)=27%11=5,地址被占用,线性探查下一地址;
H1 =(H(27)+1)%11=6,删除标志,继续探查;
H2 =(H(27)+2)%11=7,占用;
H3 =(H(27)+3)%11=8,删除标志,继续探查;
H4 =(H(27)+4)%11=9,占用;
H5 =(H(27)+5)%11=10,占用;
H6 =(H(27)+6)%11=0,占用;
H7 =(H(27)+7)%11=1,占用;
H8 =(H(27)+8)%11=2,占用;
H9 =(H(27)+9)%11=3,占用;
H10 =(H(27)+4)%11=4,占用;查找次数11与哈希表容量11相同,查找失败,插入到第一个删除标志处。
0 1 2 3 4 5 6 7 8 9 10
10 23 13 45 15 16 27 18 DELETEFLAG 20 31
总结查找、插入、删除等操作成功与失败的条件,并在hash项目中利用my_hash1验证上述过程。

3.在hash项目中利用my_hash2验证上述过程,回答以下问题:

1)my_hash1和my_hash2这两个哈希表,哪个可以直接判断同义词存在?哪个不可以?
答:my_hash1不可以判断出同义词。因为开放定址法处理冲突,使到同义词可能分散在数组的不同位置,无法判断。
my_hash2 可以判断出同义词。因为同义词在其相应位置使用链表链接起来了。

2)对比链地址法处理冲突时,哈希表的查找、插入、删除等操作与第1题开放定址法处理冲突的区别。
链地址法处理冲突时,查找、插入、删除等操作只在与哈希值对应的链表中进行操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值