数据结构--哈希表

news2024/9/21 3:14:44

文章目录

  • 哈希表查找
      • 本节提要
      • 哈希存储、查找的概念
      • 哈希函数的特点
      • 哈希函数的应用
      • 哈希函数示例
      • 哈希函数问题
      • 哈希表设计方法
      • 直接定址法
      • 除留余数法
      • 数字分析法
      • 处理冲突的方法
      • 哈希表的查找
      • 练习
      • 总结

哈希表查找

本节提要

  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题开放定址法处理冲突的区别。
链地址法处理冲突时,查找、插入、删除等操作只在与哈希值对应的链表中进行操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1956915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

普元MDM主数据管理系统与蓝凌OA系统集成案例

一、项目背景 某工程机械集团是中国工程机械产业奠基者、开创者和引领者&#xff0c;是工程机械行业具有全球竞争力、影响力的千亿级龙头企业。公司主要指标始终稳居中国工程机械行业第1位。 蓝凌OA在集团中处于一个重要角色&#xff0c;集团内各流程业务数据都需要通过OA进…

STM32通信协议 总集篇 (速记版)

名称引脚常用在双工时钟电平设备USARTTX、RX单片机和pc,单片机和单片机全双工异步单端点对点I2CSCL、SDA单片机和单片机半双工同步单端多设备SPISCLK、MOSI、MISO、CS单片机和单片机全双工同步单端多设备CANCAN_H、CAN_L智能汽车半双工异步差分多设备USBDP、DM半双工异步差分点…

目前软件测试薪资怎么样,工作好找吗?

软件测试的薪资和就业情况在不同国家和地区会有所不同。同时&#xff0c;行业的变化和经济状况也会影响薪资水平和就业机会。以下是一些一般性的信息&#xff1a; 国外软件测试薪资&#xff1a; 在发达国家&#xff0c;软件测试工程师的薪资水平通常相对较高&#xff0c;因为技…

EChart-坐标轴数值处理

写图表时&#xff0c;Y轴的数值过大&#xff0c;不太可能直接展示&#xff0c;这时候就得简写了&#xff0c;如图&#xff1a; 红框圈起来的数值表示如下&#xff1a; 1K10001M1000,0001B 1000,000,000 1KB1000,000,000,000 export function toBMK(value) {const vblValue Ma…

为什么IDEA中使用@Autowired会被警告

我们在使用IDEA编码时&#xff0c;如果用到了Autowired注解注入bean&#xff0c;会发现IDEA会给代码标个波连线&#xff0c;鼠标移动上去&#xff0c;会发下idea提示&#xff1a;不推荐使用Filed injection&#xff0c;这是Spring的核心DI&#xff08;Dendency Injection&#…

python easygui库常用方法介绍

msgbox() 弹出对话框 这是最基本的弹出对话框&#xff0c;用于显示简单的消息或提示。例如&#xff1a; import easygui easygui.msgbox("欢迎使用EasyGUI!") buttonbox() 带有多个按钮的对话框 它会显示一个带有多个按钮的对话框&#xff0c;用户点击后返回所选…

三养食品:火鸡面太辣?远不及小米辣的三分之一!

不久前&#xff0c;三养火鸡面在丹麦被召回的消息引起了全球媒体的关注。面对这一情况&#xff0c;三养食品迅速回应&#xff0c;指出丹麦方面在辣椒素的测算方法上存在错误&#xff0c;并提出了异议。大约一个月后&#xff0c;丹麦兽医和食品管理局&#xff08;以下简称DVFA&a…

ArcGIS小技巧:图斑变化分析

在做规划的过程中&#xff0c;经常会有这么个需求&#xff0c;用地方案确定后&#xff0c;需求找出规划用地和三调现状用地之间具体有哪些变化。 一方面可以用作具体规划内容的分析&#xff0c;另一方面也可以避免因为误操作而导致的错误图斑的出现。 以下图为例&#xff0c;…

FPGA实现LCD1602控制

目录 注意&#xff01; 本工程采用野火征途PRO开发板&#xff0c;外接LCD1602部件进行测试。 有偿提供代码&#xff01;&#xff01;&#xff01;可以定制功能&#xff01;&#xff01;&#xff01;有需要私信&#xff01;&#xff01;&#xff01; 一、基础知识 1.1 引脚…

Ubuntu22.04重装系统+基础配置

重装系统 note&#xff1a;备份数据&#xff0c;重装系统后home下的文件会丢失&#xff0c;所以先备份一下home的数据到其他的盘/mnt/下里。记住之前系统的DNS&#xff0c;IP和掩码。 先在Ubuntu官网下载22.04桌面版&#xff08;种子链接要用迅雷下载&#xff09;。但是版本还…

JavaScrip中删除的应用

实现功能&#xff1a; 点击删除超链接删掉 var lisdocument.getElementsByTagName("li");for (let i 0; i < lis.length; i) {lis[i].onclickfunction () {if (confirm("确定删除" this.firstChild.nodeValue "信息吗")) {this.parentNod…

聊聊,IEEE论文的含金量!这四本超赞的IEEE系列期刊,发文量超2000,谁投谁中!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解期刊最新动态&#xff01; 在学术界&#xff0c;IEEE (电气电子工程师协会) 论文被公认为高质量的研究成果。IEEE作为全球最大的专业技术组织之一&#xff0c;在电气、电子、计算机工程和科学领域具有广泛的影响力。其出版的论…

HarmonyOs~UIAbility组件的启动模式及交互

单实例模式 首先在该模块的module.json5配置 "abilities": [{..."launchType": "singleton",...}], 然后我们看一下UIAbility单实例的执行过程 tips&#xff1a;首次启动为冷启动 如果是冷启动 系统就新建该UIAbility组件的实力 若不是冷启…

【MQTT(5)】php 做一个mqtt按钮,发布触发信号

在之前博客php 做一个文件下载服务器&#xff0c;得避免跨路径工具&#xff0c;安全很重要 中加了一个按钮&#xff0c;触发物联网设备返回数据。基于mqtt开发&#xff0c;如果想知道mqtt如何搭建&#xff0c;可以看我的博客【MQTT&#xff08;1&#xff09;】服务端的搭建 效…

day13:函数基本使用

1、什么是函数 函数就相当于具备某一功能的工具 函数的使用必须遵循一个原则&#xff1a;先定义后调用2、为何要用函数 1、组织结构不清晰&#xff0c;可读性差 2、代码冗余 3、可维护性、扩展性差3、如何用函数 先定义三种定义方式后调用三种调用方式返回值三种返回值的形式…

醒醒,别睡了...讲《数据分析pandas库》了—/—<6>

一、 1、长宽格式转换 基于多重索引&#xff0c;Pandas 可以很容易地完成长型、宽型数据格式的相互转换。 1.1 转换为最简格式 stack&#xff08;&#xff09;其使用法如下&#xff1a; stack函数用于将DataFrame中的列转换为行&#xff0c;即将宽格式数据转换为长格式数据。…

【python】PyQt5中QToolButton的详细用法教学与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

jeecguniapp开发小结

一、问题:app发行后图片不显示 解决:绝对路径改成相对路径 另外&#xff1a;避免发行上线图片变形要给到图标或图片具体宽高 //绝对路径 <img src"/static/home/128/wendang.png" style"width:90rpx;height:90rpx;"/> //相对路径 <img src"…

Anaconda环境迁移方法

前言 当我们需要将在一个新电脑上配置Anaconda的环境时&#xff0c;联网的情况下是需要在Anaconda Prompt上安装python环境以及一堆库&#xff1b;离线的情况下则需要用wheel文件一个一个装&#xff0c;十分麻烦。因此方便起见&#xff0c;我们可以将当前电脑上已有的Anaconda…