哈希表哈希桶

news2024/12/23 19:34:18

目录

哈希概念

哈希冲突

哈希函数 

一、直接定址法(常用)

二、除留余数法(常用)

三、平方取中法

四、折叠法

五、随机数法

六、数字分析法

哈希冲突解决

开散列—— 链地址法(拉链法、哈希桶)

闭散列 —— 开放定址法

一、线性探测 

二、二次探测


哈希概念

顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。搜索的效率取决于搜索过程中元素的比较次数,因此顺序结构中查找的时间复杂度为O(N),平衡树中查找的时间复杂度为树的高度O(logN)。

而最理想的搜索方法是,可以不经过任何比较,一次直接从表中得到要搜索的元素,即查找的时间复杂度为O(1)。

如果构造一种存储结构,该结构能够通过某种函数使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时就能通过该函数很快找到该元素。

向该结构当中插入和搜索元素的过程如下:

  • 插入元素: 根据待插入元素的关键码,用此函数计算出该元素的存储位置,并将元素存放到此位置。
  • 搜索元素: 对元素的关键码进行同样的计算,把求得的函数值当作元素的存储位置,在结构中按此位置取元素进行比较,若关键码相等,则搜索成功。

该方式即为哈希(散列)方法, 哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(散列表)。

例如,集合{1, 7, 6, 4, 5, 9}
哈希函数设置为:h a s h ( k e y ) = k e y % c a p a c i t y hash(key)=key\%capacityhash(key)=key%capacity,其中capacity为存储元素底层空间的总大小。
若我们将该集合存储在capacity为10的哈希表中,则各元素存储位置对应如下:

用该方法进行存储,在搜索时就只需通过哈希函数判断对应位置是否存放的是待查找元素,而不必进行多次关键码的比较,因此搜索的速度比较快。

哈希冲突

不同关键字通过相同哈希函数计算出相同的哈希地址,这种现象称为哈希冲突或哈希碰撞。我们把关键码不同而具有相同哈希地址的数据元素称为“同义词”。

例如,在上述例子中,再将元素11插入当前的哈希表就会产生哈希冲突。 因为元素11通过该哈希函数得到的哈希地址与元素1相同,都是下标为1的位置
h a s h ( 11 ) = 11 % 10 = 1 hash(11)=11\%10=1hash(11)=11%10=1。

哈希函数 

引起哈希冲突的一个原因可能是哈希函数设计不够合理。

哈希函数设计的原则:

  1. 哈希函数的定义域必须包括需要存储的全部关键码,且如果散列表允许有m个地址,其值域必须在0到m-1之间。
  2. 哈希函数计算出来的地址能均匀分布在整个空间中。
  3. 哈希函数应该比较简单。

 常见的哈希函数如下:

一、直接定址法(常用)

取关键字的某个线性函数为哈希地址:H a s h ( K e y ) = A ∗ K e y + B Hash(Key)=A*Key+BHash(Key)=A∗Key+B。

优点:每个值都有一个唯一位置,效率很高,每个都是一次就能找到。
缺点:使用场景比较局限,通常要求数据是整数,范围比较集中。
使用场景:适用于整数,且数据范围比较集中的情况。

二、除留余数法(常用)

设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:H a s h ( K e y ) = K e y % p ( p < = m ) Hash(Key)=Key\%p(p<=m)Hash(Key)=Key%p(p<=m),将关键码转换成哈希地址。

优点:使用场景广泛,不受限制。
缺点:存在哈希冲突,需要解决哈希冲突,哈希冲突越多,效率下降越厉害。

三、平方取中法

假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址。

使用场景:不知道关键字的分布,而位数又不是很大的情况。

四、折叠法

折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按哈希表表长,取后几位作为哈希地址。

使用场景:折叠法适合事先不需要知道关键字的分布,或关键字位数比较多的情况。

五、随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H a s h ( K e y ) = r a n d o m ( K e y ) Hash(Key)=random(Key)Hash(Key)=random(Key),其中random为随机数函数。

使用场景:通常应用于关键字长度不等时。

六、数字分析法

设有n个d位数,每一位可能有r种不同的符号,这r中不同的符号在各位上出现的频率不一定相同,可能在某些位上分布比较均匀,每种符号出现的机会均等,而在某些位上分布不均匀,只有几种符号经常出现。此时,我们可根据哈希表的大小,选择其中各种符号分布均匀的若干位作为哈希地址。

例如:

假设要存储某家公司员工登记表,如果用手机号作为关键字,那么极有可能前7位都是相同的,那么我们可以选择后面的四位作为哈希地址。

如果这样的抽取方式还容易出现冲突,还可以对抽取出来的数字进行反转(如1234改成4321)、右环位移(如1234改成4123)、左环位移(如1234改成2341)、前两数与后两数叠加(如1234改成12+34=46)等操作。

数字分析法通常适合处理关键字位数比较大的情况,或事先知道关键字的分布且关键字的若干位分布较均匀的情况。

注意:哈希函数设计的越精妙,产生哈希冲突的可能性越低,但是无法避免哈希冲突。

哈希冲突解决

开散列—— 链地址法(拉链法、哈希桶)

开散列,又叫链地址法(拉链法),首先对关键码集合用哈希函数计算哈希地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

闭散列解决哈希冲突,采用的是一种报复的方式,“我的位置被占用了我就去占用其他位置”。而开散列解决哈希冲突,采用的是一种乐观的方式,“虽然我的位置被占用了,但是没关系,我可以‘挂’在这个位置下面”。

与闭散列不同的是,这种将相同哈希地址的元素通过单链表链接起来,然后将链表的头结点存储在哈希表中的方式,不会影响与自己哈希地址不同的元素的增删查改的效率,因此开散列的负载因子相比闭散列而言,可以稍微大一点。

  • 闭散列的开放定址法,负载因子不能超过1,一般建议控制在[0.0, 0.7]之间。
  • 开散列的哈希桶,负载因子可以超过1,一般建议控制在[0.0, 1.0]之间。

在实际中,开散列的哈希桶结构比闭散列更实用,主要原因有两点:

  1. 哈希桶的负载因子可以更大,空间利用率高。
  2. 哈希桶在极端情况下还有可用的解决方案。

 哈希桶的极端情况就是,所有元素全部产生冲突,最终都放到了同一个哈希桶中,此时该哈希表增删查改的效率就退化成了O(N):
这时,我们可以考虑将这个桶中的元素,由单链表结构改为红黑树结构,并将红黑树的根结点存储在哈希表中。

在这种情况下,就算有十亿个元素全部冲突到一个哈希桶中,我们也只需要在这个哈希桶中查找30次左右,这就是所谓的“桶里种树”。

为了避免出现这种极端情况,当桶当中的元素个数超过一定长度,有些地方就会选择将该桶中的单链表结构换成红黑树结构,比如在JAVA中比较新一点的版本中,当桶当中的数据个数超过8时,就会将该桶当中的单链表结构换成红黑树结构,而当该桶当中的数据个数减少到8或8以下时,又会将该桶当中的红黑树结构换回单链表结构。

但有些地方也会选择不做此处理,因为随着哈希表中数据的增多,该哈希表的负载因子也会逐渐增大,最终会触发哈希表的增容条件,此时该哈希表当中的数据会全部重新插入到另一个空间更大的哈希表,此时同一个桶当中冲突的数据个数也会减少,因此不做处理问题也不大。
 

闭散列 —— 开放定址法

闭散列,也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表种必然还有空位置,那么可以把产生冲突的元素存放到冲突位置的“下一个”空位置中去。

一、线性探测 

当发生哈希冲突时,从发生冲突的位置开始,依次向后探测,直到找到下一个空位置为止。

Hi=(H0+i)%m (i=1,2,3,...)

H0:通过哈希函数对元素的关键码进行计算得到的位置。
Hi:冲突元素通过线性探测后得到的存放位置。
m:表的大小。

我们将数据插入到有限的空间,那么空间中的元素越多,插入元素时产生冲突的概率也就越大,冲突多次后插入哈希表的元素,在查找时的效率必然也会降低。介于此,哈希表当中引入了负载因子(载荷因子):

负载因子 = 表中有效数据个数 / 空间的大小

  • 负载因子越大,产出冲突的概率越高,增删查改的效率越低。
  • 负载因子越小,产出冲突的概率越低,增删查改的效率越高。

但负载因子越小,也就意味着空间的利用率越低,此时大量的空间实际上都被浪费了。对于闭散列(开放定址法)来说,负载因子是特别重要的因素,一般控制在0.7~0.8以下,超过0.8会导致在查表时CPU缓存不命中(cache missing)按照指数曲线上升。
因此,一些采用开放定址法的hash库,如JAVA的系统库限制了负载因子为0.75,当超过该值时,会对哈希表进行增容。

线性探测的优点:实现非常简单。
线性探测的缺点:一旦发生冲突,所有的冲突连在一起,容易产生数据“堆积”,即不同关键码占据了可利用的空位置,使得寻找某关键码的位置需要多次比较(踩踏效应),导致搜索效率降低。

二、二次探测

线性探测的缺陷是产生冲突的数据堆积在一块,这与其找下一个空位置有关系,因为找空位置的方式就是挨着往后逐个去找,因此二次探测为了避免该问题,找下一个空位置的方法为:

Hi=(H0+i*i)%m (i=1,2,3,...)

H0:通过哈希函数对元素的关键码进行计算得到的位置。
Hi:冲突元素通过二次探测后得到的存放位置。
m:表的大小。

采用二次探测为产生哈希冲突的数据寻找下一个位置,相比线性探测而言,采用二次探测的哈希表中元素的分布会相对稀疏一些,不容易导致数据堆积。

和线性探测一样,采用二次探测也需要关注哈希表的负载因子,例如,采用二次探测将数据插入到表长为20的哈希表,产生冲突的次数也会有所减少:

因此,闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。

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

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

相关文章

什么是专利?如何申请专利?

专利&#xff08;patent)从字面上讲&#xff0c;“专利”即是指专有的利益和权利。专利一词来源于拉丁语Litterae patentes&#xff0c;意为公开的信件或公共文献&#xff0c;是中世纪的君主用来颁布某种特权的证明&#xff0c;后来指英国国王亲自签署的独占权利证书。专利是世…

PhpStorm安装篇

PhpStorm安装篇: 下载地址 : 进入官网下PhpStorm: PHP IDE and Code Editor from JetBrains 下载完之后&#xff0c;安装包 安装目录建议不要放C盘&#xff0c;放其他盘&#xff0c;其他直接一直点 next &#xff0c;到结束 安装完&#xff0c;打开编辑器 注册账号并登录后…

《Flink学习笔记》——第十章 容错机制

10.1 检查点&#xff08;Checkpoint&#xff09; 为了故障恢复&#xff0c;我们需要把之前某个时间点的所有状态保存下来&#xff0c;这份“存档”就是“检查点” 遇到故障重启的时候&#xff0c;我们可以从检查点中“读档”&#xff0c;恢复出之前的状态&#xff0c;这样就可以…

实例047 如何为MDI类型窗体设置背景图片

实例说明 MDI窗体是一种应用非常广泛的窗体类型&#xff0c;在一个主窗体内包含多个子窗体&#xff0c;子窗体永远不会显示在主窗体的外面。当子窗体不能完全的显示在主窗体中时&#xff0c;主窗体会显示滚动条来调整可视范围&#xff0c;在其他开发环境中为MDI窗体添加背景图…

Nature commun |晚期胰腺导管腺癌中自发进化的祖细胞niches逃避Yap癌基因成瘾

“致癌基因成瘾”用于描述癌细胞通常表现出对一种或多种致癌驱动因素的严格依赖性以维持肿瘤生长和进展的现象。几乎所有肿瘤在药物缓解后都会出现最终的肿瘤复发。那么&#xff0c;在晚期胰腺导管腺癌(PDAC)中结合RNA-seq和Cut&Tag技术对肿瘤自发复发研究有什么样的影响呢…

趣解建造者模式之网红小王购车记

一、前言 本文章是关于设计模式中的建造者模式的&#xff0c;也称构建者模式/生成器模式&#xff0c;英文我们称之为Builder Pattern。在开展讲解之前&#xff0c;我们先把该模式的定义了解一下。 建造者模式的定义&#xff1a; 该模式可以实现产品的封装构造过程&#xff0c…

《2023 中国人工智能人才学习白皮书》完整下载!

Datawhale发布 2023 中国人工智能人才学习白皮书 I 导读 日前&#xff0c;由 Datawhale 联合上海白玉兰开源开放研究院、和鲸科技、江南大学教育信息化研究中心编写的《2023中国人工智能人才学习白皮书》&#xff08;下简称“白皮书”&#xff09;于8月24日正式发布。 学界大咖…

数字化转型的关键点是什么?

数字化转型的关键点是指企业或组织在适应并利用数字技术的过程中需要关注和把握的关键要素。以下是数字化转型的关键点&#xff1a; 领导力和战略&#xff1a;数字化转型需要高层领导层的支持和积极参与。领导层需要制定明确的数字化战略&#xff0c;并将其与企业的整体战略相结…

AI大模型的使用-语义检索,利用Embedding优化你的搜索功能

Embedding 向量适合作为一个中间结果&#xff0c;用于传统的机器学习场景&#xff0c;比如分类、聚类。 Completion 接口&#xff0c;一方面可以直接拿来作为一个聊天机器人&#xff0c;另一方面&#xff0c;你只要善用提示词&#xff0c;就能完成合理的文案撰写、文本摘要、机…

深度解析 PostgreSQL Protocol v3.0(一)

引言 PostgreSQL 使用基于消息的协议在前端&#xff08;也可以称为客户端&#xff09;和后端&#xff08;也可以称为服务器&#xff09;之间进行通信。该协议通过 TCP/IP 和 Unix 域套接字支持。 《深度解析 PostgreSQL Protocol v3.0》系列技术贴&#xff0c;将带大家深度了…

docker部署nginx,部署springboot项目,并实现访问

一、先部署springboot项目 1、安装docker&#xff1a; yum install docker -y 2、启动docker&#xff1a; service docker start 重启&#xff1a; service docker restart 3、查看版本&#xff1a; docker -v 4、使设置docker.service生效&#xff08;路径&#xff1a;…

【数据分析,附源码】MATLAB R2022b安装教程

软件下载 软件&#xff1a;MATLAB版本&#xff1a;2022b语言&#xff1a;简体中文大小&#xff1a;19.37G安装环境&#xff1a;Win11/Win10硬件要求&#xff1a;CPU2.6GHz 内存8G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com/s/1R1…

ssm高校教师科研信息展示网站源码和论文

ssm高校教师科研信息展示网站源码和论文095 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面…

Mybatis1.9 批量删除

1.9 批量删除 1.9.1 编写接口方法1.9.2 编写SQL语句1.9.3 编写测试方法 如上图所示&#xff0c;用户可以选择多条数据&#xff0c;然后点击上面的 删除 按钮&#xff0c;就会删除数据库中对应的多行数据。 1.9.1 编写接口方法 在 BrandMapper 接口中定义删除多行数据的方法。…

Mysql高阶语句 (一)

一、常用查询 &#xff08;增、删、改、查&#xff09; 对 MySQL 数据库的查询&#xff0c;除了基本的查询外&#xff0c;有时候需要对查询的结果集进行处理。 例如只取 10 条数据、对查询结果进行排序或分组等等 1、按关键字排序 PS:类比于windows 任务管理器 使用 SELECT 语句…

成都瀚网科技有限公司:抖店精选联盟企业是什么?

我很高兴为您提供有关如何加入抖店特色联盟企业以及加入的好处的信息。在这篇文章中&#xff0c;我将为大家详细介绍如何申请加入抖店精选的关联公司&#xff0c;并讲解加入的好处。希望能够帮助您更好地了解和使用抖店精选联盟企业平台。 1、如何加入抖店精选联盟企业&#xf…

亚马逊鲲鹏系统是怎么操作测评的

亚马逊鲲鹏系统可以注册亚马逊买家号、养号、下单留评等&#xff0c;是一款功能比较齐全的测评软件&#xff0c;具体操作如下&#xff1a; 首先我们需要先准备好买家账号&#xff0c;账号可以直接去购买已经注册好了的账号&#xff0c;也可以准备好账号所需要的一些邮箱、ip、…

做邮件营销前,这些注意事项一定要知晓

邮件营销是一种有效的网络营销手段&#xff0c;可以帮助企业与潜在客户建立长期联系&#xff0c;促进销售和品牌认知。相比于其他的营销手段&#xff0c;邮件营销针对性更强&#xff0c;可以根据不同类型用户所具有的特征和属性进行营销。其次&#xff0c;邮件营销的覆盖范围较…

EPICS asyn连接测试例程

1) 用makeBaseApp.pl新建一个EPICS IOC的目录结构&#xff1a; rootorangepi5:/usr/local/EPICS/program/testConnect# ls configure iocBoot Makefile testConnectApp2) 编辑configure目录下的RELEASE文件&#xff0c;定义asyn模块所在的路径&#xff1a; ... SUPPORT/us…

Java“牵手”1688拍立淘接口数据,图片搜索1688商品,图片识别商品接口,1688API申请指南

1688商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取1688商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问1688商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…