hash表如何形成,hash函数如何计算,什么是hash冲突 如何解决 ,Golang map的底层原理及扩容机制

散列表

散列表(hash表):根据给定的关键字来计算出关键字在表中的地址的数据结构。也就是说,散列表建立了关键字和
存储地址之间的一种直接映射关系。

问题:如何建立映射管血

散列函数:一个把查找表中的关键字映射成该关键字对应的地址的函数,记为Hash(key)=Addr.

hash冲突

散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为“冲突
这些发生碰撞的不同关键字称为同义词。

image-20240730141829195

构造散列函数的条件:

  • 散列函数的定义域必须包含全部需要存储的关键字,而值域的范围则依赖于散列表的大小或地址范围。
  • 散列函数计算出来的地址应该能等概率、均匀地分布在整个地址空间,从而减少冲突的发生。
  • 散列函数应尽量简单,能够在较短的时间内就计算出任一关键字对应的散列地址。
1.常用的Hash函数的构造方法:
  • 直接定址法:直接取关键字的某个线性函数值为散列地址,散列函数为H(key)=axkey+b。式中,a和b是
    常数。这种方法计算最简单,并且不会产生冲突
  • 除留余数法:假定散列表表长为m,取一个不大于m但最接近或等于m的质数p,利用以下公式把关键字
    转换成散列地址。散列函数为H(kev)=key %p
    除留余数法的关键是选好p,使得每一个关键字通过该函数转换后等概率地映射到散列空间上的任一地址
    从而尽可能减少冲突的可能性
  • 数字分析法
    设关键字是r进制数(如十进制数),而r个数码在各位上出现的频率不一定相同,
    可能在某些位上分布均匀些
    每种数码出现的机会均等;而在某些位上分布不均匀,只有某几种数码经常出现,
    则应选取数码分布较为均匀
    的若干位作为散列地址。这种方法适合于已知的关键字集合

image-20240730142613377

手机号后四位分布比较均与 如果key为手机号那么取手机号后四位为散列值

4.平方取中法
顾名思义,取关键字的平方值的中间几位作为散列地址。具体取多少位要看实际情况而定。这种方法得
到的散列地址与关键字的每一位都有关系,使得散列地址分布比较均匀。

Eg

12342=1522756 取中间三位227作为散列地址

23452=5499025 取中间三位990作为散列地址

5.折叠法

将关键字分割成位数相同的几部分 (最后一部分的位数可以短一些),然后取这几部分的叠加和作为
散列地址,这种方法称为折叠法。关键字位数很多,而且关键字中每一位上数字分布大致均匀时,可
以采用折香法得到散列地址。
Eg:关键字为1234567890散列表表长为3位可以将关键字分为四组每组3位
123456|7890然后这四组叠加求和123+456+789+0=1368 然后取后3位就能得到散列地址为368

2.常用的Hash函数的冲突处理办法
1.开放定址法

​ :将产生冲突的Hash地址作为自变量,通过某种冲突解决函数得到一个新的空闲的Hash地址。

		1)   线性探测法: 冲突发生时,顺序查看表中下一个单元 (当探测到表尾地址m-1时,探测地址是表首地址0),直到找出一个空闲单元 (当表未填满时一定能找到一个空闲单元)或查遍全表。

image-20240730154952929

如上图,11 、19、27经过运算后的映射下标都是3,由于3被最开始的11占用,那19就不得不后移占住后面空着的下表,这样就会产生连锁反应导致原来hash值是4的key也要后移,这样查找起来就非常麻烦

比如我找27,先计算得出27的hash值是3,但发下3下面存的11,只能往后找4 – 19不是,继续遍历到5 – 17 找到了

2)平方探测法:设发生冲突的地址为d,平方探测法得到的新的地址序列为d+12,d-12,d+22,d-22
平方探测法是一种较好的处理冲突的方法,可以避免出现“堆积”问题,它的缺点是不能探测到散列
表上的所有单元,但至少能探测到一半单元。

image-20240730155513651

3)再散列法:又称为双散列法。需要使用两个散列函数,当通过第一个散列函数H(Key)得到的地址发
生冲突时,则利用第二个散列函数Hash2(Kev)计算该关键字的地址增量。

image-20240730155651274

4)伪随机序列法:当发生地址冲突时,地址增量为伪随机数序列,称为伪随机序列法。

2.拉链法:

对于不同的关键字可能会通过散列函数映射到同一地址,为了避免非同义词
发生冲突,可以把所有的同义词存储在一个线性链表中,这个线性链表由其散列地址唯
标识。拉链法适用于经常进行插入和删除的情况

3.散列表的查找过程

类似于构造散列表,给定一个关键字Key。
先根据散列函数计算出其散列地址。然后检查散列地址位置有没有关键字.
1)如果没有,表明该关键字不存在,返回查找失败。
2)如果有,则检查该记录是否等于关键字。

  • 如果等于关键字,返回查找成功。
  • 如果不等于,则按照给定的冲突处理办法来计算下一个散列地址,再用该地址去执行上述过程。
4.散列表的查找性能

性能和装填因子有关

什么是装填因子?

image-20240730160416593

image-20240730160759116

Golang中map的hash值是如何计算如何存的?

在日常编程中,map的底层也是hash表,但map 的 key 键不仅仅是数字,还可能是字符串。由于我们之前讨论的哈希函数主要是针对数字进行计算的,因此,当 key 为字符串时,首先需要将字符串转化为整数,然后再经过哈希函数的运算产生哈希值。

在 Go 中,map 的哈希值会通过取模运算(或其他方式)转换成哈希表中的一个具体位置,这个位置称为映射地址。映射地址通常对应于一个桶,桶是一个存储多个键值对的容器。每个桶可以存储多个键值对,以处理哈希冲突。桶的数量通常与哈希表的容量有关。

溢出桶:如果主桶已满,则会创建一个溢出桶,将多余的键值对存储在溢出桶中。如果溢出桶也满了,就会继续创建新的溢出桶,形成一个链表结构。

image-20240730161624131

ps:个人认为桶和线性链表及其相似

go map的扩容机制

扩容的时机装载因⼦超过⼀定的阈值或者使⽤了太多的溢出桶时。

扩容的规则:
  1. 等量扩容 使⽤溢出桶太多的时候会进⾏等量扩容。申请和原来等量的内容,将原来的数据重新整理

后,写⼊到新的内存中。可以简单的认为是⼀次内存整理,⽬的是提⾼查询效率。

  1. 增量扩容 分成两步: 第⼀步进⼊扩容状态,先申请⼀块新的内存,翻倍增加桶的数量,此时

buckets指向新分配的桶,oldbuckets指向原来的桶。 第⼆步,重新计算⽼的桶中的哈希值在新

的桶内的位置(取模或者位操作),将旧数据⽤渐进式的⽅式拷⻉到新的桶中。

渐进式迁移分两块,⼀⽅⾯会从第⼀个桶开始,顺序迁移每⼀个桶,如果下⼀个桶已经迁移,则跳

过。另⼀⽅⾯,当我们操作某⼀个桶的元素时,会迁移两个桶,进⽽保证经过⼀些操作后⼀定能够完

成迁移。

访问迁移的map时会放生什么?

当我们访问⼀个正在迁移的Map时,如果存在oldbuckets,那么直接去中oldbuckets寻找数据。当

我们遍历⼀个正在迁移的Map时,新的和旧的就会遍历,如果⼀个旧的的桶已经迁移⾛了,那么就直

接跳过,反正不在旧的就在新的⾥。Map遍历本⾝就是⽆序的。

定能够完

成迁移。

访问迁移的map时会放生什么?

当我们访问⼀个正在迁移的Map时,如果存在oldbuckets,那么直接去中oldbuckets寻找数据。当

我们遍历⼀个正在迁移的Map时,新的和旧的就会遍历,如果⼀个旧的的桶已经迁移⾛了,那么就直

接跳过,反正不在旧的就在新的⾥。Map遍历本⾝就是⽆序的。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle语法介绍

Oracle数据库是关系型数据库管理系统之一,其SQL语法遵循标准的SQL规范,但也有一些自己的扩展。以下是一些Oracle SQL语法的基本示例: 1.选择数据: SELECT * FROM my_table; 1.插入数据: INSERT INTO my_table (colum…

RocketMQ事务消息机制原理

RocketMQ工作流程 在RocketMQ当中,当消息的生产者将消息生产完成之后,并不会直接将生产好的消息直接投递给消费者,而是先将消息投递个中间的服务,通过这个服务来协调RocketMQ中生产者与消费者之间的消费速度。 那么生产者是如何…

【设计模式】工厂模式详解

1.简介 工厂模式是一种创建型设计模式,通过提供一个接口或抽象类来创建对象,而不是直接实例化对象。工厂模式的主要思想是将对象的创建与使用分离,使得创建对象的过程更加灵活和可扩展。 工厂模式主要包括以下角色: 抽象工厂&a…

地铁深基坑结构施工预警实时监测系统测点布设

01 基坑监测背景 随着我国城市建设的发展,基坑规模和开挖深度不断增加。在基坑开挖过程中,如何尽快的在第一时间了解基坑的变形情况,并动态评估基坑的结构安全,避免事故的发生。与其它监测方法相比,实现自动化监测、信…

gradio 之页面布局

输出组件的可交互,默认垂直排列 import gradio as gr def greet(name):return "Hello " name "!" with gr.Blocks() as demo:name gr.Textbox(label"Name")# 不可交互# output gr.Textbox(label"Output Box")# 可交互…

超声波清洗机哪个品牌比较好耐用?好用的超声波清洗机推荐

随着科技的发展,超声波清洗机已经慢慢出现在我们日常生活中了。像日常使用的小物品,如手表和首饰等,时间久了,难免会积累灰尘,滋生细菌。那么应该如何进行彻底清洁呢?超声波清洗机可以给我们答案&#xff0…

Move生态:从Aptos和Sui到Starcoin的崛起

区块链技术自诞生以来,已经经历了多个发展阶段和技术迭代。近年来,随着智能合约平台的不断演进,以Move语言为核心的生态系统逐渐崭露头角。Move语言以其安全性、灵活性和高效性吸引了大量开发者和项目方的关注。在Move生态中,Apto…

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级 在开发MES系统的过程中,涉及到了平板端APP的开发,既然是移动端的应用,那么肯定需要APP版本的自动更新功能。 查阅相关资料后,在uniapp的…

【数据结构】——双链表的实现(赋源码)

双链表的概念和结构 双链表的全称叫做:带头双向循环链表 它的结构示意图如下 注意:这⾥的“带头”跟前⾯我们说的单链表的“头结点”是两个概念,实际前⾯的在单链表阶段称呼不严谨,但是为了读者们更好的理解就直接称为单链表的头…

Transformer——逐步详解架构和完整代码搭建

好久没更新博客,后面更新会勤一些。今天想聊一下Transformer,Transformer在NLP和CV领域都有着重要的价值,甚至可以看作是一个基础模型,这篇博客将通过详细代码深入解析Transformer模型总体架构图各个部分的的作用和搭建:论文链接&…

遥感领域新方向!Mamba+RS论文汇总!

本文总结了将Mamba应用至遥感领域的相关论文(14篇),涉及到的论文见文末链接,具体如下: 文章目录 1. 遥感图像处理2. 多/高光谱图像分类3. 变化检测/语义分割4. 遥感图像融合/超分辨率 1. 遥感图像处理 论文题目&#…

6.3 面向对象技术-设计模式

设计模式 创建型模式 结构型模式 行为型模式 真题

配置本地开发服务器代理请求以及登录模块开发(二)

项目初始化完成之后,准备开始进行项目的开发,首先配置好开发环境作为整个项目的基础 一、配置代理 1、config/proxy.ts配置代理 export default {// 如果需要自定义本地开发服务器 请取消注释按需调整dev: {// localhost:8000/api/** -> https://p…

第07课 Scratch入门篇:水果音乐钢琴

水果音乐钢琴 入门篇适合新手,如您已经学过,可以忽略本节课! 一、故事背景: 在一个充满创意和想象的奇妙世界里,有一架与众不同的钢琴——水果音乐钢琴。这架钢琴的键盘不是由普通的黑白键组成,而是由各种…

http post请求 - 最简测试环境 - 使用flask

1.缘起 工作中,我们有时需要测试web post功能是否正常。这类测试,客户端的请求很容易实现,比如portman,比如非常简单的命令行curl语法: curl -X POST http://127.0.0.1:5000/post-endpoint/ -F "warning_image/p…

鸿蒙 HarmonyOS NEXT端云一体化开发-云数据库篇

一、概述 云数据库是一款基于对象模型的数据库,采用存储区、对象类型和对象三级结构。 数据模型 存储区 存储区是一个独立的数据存储区域,多个数据存储区之间相互独立,每个存储区拥有完全相同的对象类型定义 --类似于关系型数据库中的da…

一番赏小程序开发,为消费者带来更多新鲜体验

一番赏作为经典的潮玩方式,深受消费者的喜爱,一番赏还会与不同的热门IP合作,不断推出新的赏品,吸引众多粉丝。赏品的内容非常丰富,从手办、公仔玩具等,还设有隐藏款和最终赏商品,对玩家拥有着非…

哲学CSSCI南大核心期刊论文投稿推荐(含发表方向)

发表哲学方向的C刊论文,却在选刊上一直找不到合适的。本文介绍14本哲学CSSCI南大核心期刊名单,帮助您快速找到哲学类期刊! 哲学类CSSCI核心期刊推荐: 1、逻辑学研究 发表内容方向:符号逻辑、非形式逻辑、逻辑与哲学、…

Synchronized的锁升级过程是怎样的?

文章目录 一、Synchronized的使用1、修饰实例方法2、修饰静态方法3、修饰代码块4、总结: 二、Monitor1、Java对象头1.1 32 位虚拟机的对象头1.2 64位虚拟机的对象头 2、Mark Word 结构3、Moniter4、Synchronized 字节码5、轻量级锁6、锁膨胀7、自旋优化8、偏向锁9、…

命令行使用ADB,不用root,完美卸载小米预装软件

ADB安装与运行 install java 下载安装 注意选择JDK17以上版本 https://www.oracle.com/java/technologies/downloads/#jdk22-windows 选择中间的安装文件下载 编辑系统变量 C:\Program Files (x86)\Java\jdk-22 C:\Program Files (x86)\Java\jdk-22\bin 把C:\Progra…