1.哈希的概念

哈希(hash)⼜称散列,是⼀种组织数据的⽅式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系,查找时通过这个哈希函数计算出Key存储的位置,进⾏快速查找。

1.2.直接定址法

当关键字的范围⽐较集中时,直接定址法就是⾮常简单⾼效的⽅法,⽐如⼀组关键字都在[0,99]之间,那么我们开⼀个100个数的数组,每个关键字的值直接就是存储位置的下标。再⽐如⼀组关键字值都在[a,z]的⼩写字⺟,那么我们开⼀个26个数的数组,每个关键字acsii码-a ascii码就是存储位置的下标。也就是说直接定址法本质就是⽤关键字计算出⼀个绝对位置或者相对位置

1.3.哈希冲突 

直接定址法的缺点也⾮常明显,当关键字的范围⽐较分散时,就很浪费内存甚⾄内存不够⽤。

这⾥存在的⼀个问题就是,两个不同的key可能会映射到同⼀个位置去,这种问题我们叫做哈希冲突。

1.4.负载因子

假设哈希表中已经映射存储了N个值,哈希表的大小为M,那么 负载因子 = N/M ,负载因⼦有些地⽅也翻译为载荷因⼦/装载因⼦等,他的英⽂为load factor。负载因⼦越⼤,哈希冲突的概率越⾼,空间利⽤率越⾼;负载因⼦越⼩,哈希冲突的概率越低,空间利⽤率越低。

1.5.将关键字转为整数

我们将关键字映射到数组中位置,⼀般是整数好做映射计算,如果不是整数,我们要想办法转换成整数。后面给具体实现方法。

2.哈希函数

⼀个好的哈希函数应该让N个关键字被等概率的均匀的散列分布到哈希表的M个空间中,但是实际中却很难做到,但是我们要尽量往这个⽅向去考量设计。

2.1除法散列法

假设哈希表的⼤⼩为M,那么通过key除以M的余数作为映射位置的下标,也就是哈希函数为:h(key) = key % M。

当使⽤除法散列法时,要尽量避免M为某些值,如2的幂,10的幂等。如果是2^x ,那么key %

2^x本质相当于保留key的后X位,那么后x位相同的值,计算出的哈希值都是⼀样的,就冲突了。如: {63 , 31}看起来没有关联的值,如果M是16,也就是2^4 ,那么计算出的哈希值都是15,因为63的⼆ 进制后8位是 00111111,31的⼆进制后8位是 00011111。如果是10^2 ,就更明显了,保留的都是10进值的后x位,如:{112, 12312},如果M是100,也就是10^2 ,那么计算出的哈希值都是12。

当使⽤除法散列法时,建议M取不太接近2的整数次幂的⼀个质数(素数)。

3.处理哈希冲突

实践中哈希表⼀般还是选择除法散列法作为哈希函数,当然哈希表⽆论选择什么哈希函数也避免不了冲突,那么插⼊数据时,如何解决冲突呢?主要有两种两种⽅法,开放定址法和链地址法。

3.1开放定址法

在开放定址法中所有的元素都放到哈希表⾥,当⼀个关键字key⽤哈希函数计算出的位置冲突了,则按照某种规则找到⼀个没有存储数据的位置进⾏存储,开放定址法中负载因⼦⼀定是⼩于1的。
1.线性探测:
1.1 从发⽣冲突的位置开始,依次线性向后探测,直到寻找到下⼀个没有存储数据的位置为⽌,如果⾛
到哈希表尾,则回绕到哈希表头的位置。1.2 h(key) = hash0 = key % M,, hash0位置冲突了,则线性探测公式为:
hc(key,i) = hashi = (hash0 + i) % M, i = {1, 2, 3, ..., M − 1},
因为负载因⼦⼩于1,则最多探测M-1次,⼀定能找到⼀个存储key的位置。2.⼆次探测:
2.1 从发⽣冲突的位置开始,依次左右按⼆次⽅跳跃式探测,直到寻找到下⼀个没有存储数据的位置为
⽌,如果往右⾛到哈希表尾,则回绕到哈希表头的位置;如果往左⾛到哈希表头,则回绕到哈希表
尾的位置;
2.2 h(key) = hash0 = key % M , hash0位置冲突了,则⼆次探测公式为:
hc(key,i) = hashi = (hash0 ± i^2 ) % M, i = {1, 2, 3, ..., M/2}
2.3 ⼆次探测当 hashi = (hash0 − i^2)%M 时,当hashi<0时,需要hashi += M

3.2扩容:

这⾥哈希表负载因⼦控制在0.7,当负载因⼦到0.7以后我们就需要扩容了,我们还是按照2倍扩容,但是同时我们要保持哈希表⼤⼩是⼀个质数,第⼀个是质数,2倍后就不是质数了。那么如何解决了,⼀种⽅案就是除法散列中Java HashMap的使⽤2的整数幂,但是计算时不能直接取模的改进⽅法。另外⼀种⽅案是sgi版本的哈希表使⽤的⽅法,给了⼀个近似2倍的质数表,每次去质数表获取扩容后的⼤⼩。

3.3key不能取模的问题

当key是string/自定义等类型时,key不能取模, 那么我们需要给HashTable增加⼀个仿函数,这个仿函 数⽀持把key转换成⼀个可以取模的整形,如果key可以转换为整形并且不容易冲突,那么这个仿函数 就⽤默认参数即可,如果这个Key不能转换为整形,我们就需要⾃⼰实现⼀个仿函数传给这个参数,实 现这个仿函数的要求就是尽量key的每值都参与到计算中,让不同的key转换出的整形值不同。string 做哈希表的key⾮常常⻅,所以我们可以考虑把string特化⼀下。

3.4开放定址法代码实现

*3.4链地址法

哈希表中存储⼀个指针,没有数据映射这个位置时,这个指针为空,有多个数据映射到这个位置时,我们把这些冲突的数据链接成⼀个链表,挂在哈希表这个位置下⾯,链地址法也叫做拉链法或者哈希桶。

扩容:

开放定址法负载因⼦必须⼩于1,链地址法的负载因⼦就没有限制了,可以⼤于1。负载因⼦越⼤,哈希冲突的概率越⾼,空间利⽤率越⾼;负载因⼦越⼩,哈希冲突的概率越低,空间利⽤率越低;stl中unordered_xxx的最⼤负载因⼦基本控制在1,⼤于1就扩容。
极端场景:
如果极端场景下,某个桶特别⻓怎么办?这是把链表转换成红黑树,提供一个思路。

3.5链地址法代码实现

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

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

相关文章

IoTDB TTL不生效

问题 时序数据库 IoTDB 1.3.0 版本数据库的 TTL 设置为两天&#xff0c;show databases details 看到设置也是正确的&#xff0c;怎么还是可以查到好几天前的数据&#xff1f;因为有很多不活跃的测点&#xff0c;所以专门设置了两天过期&#xff0c;有什么办法可以自动清理呢&…

【C++基础】Lambda 函数 基础知识讲解学习及难点解析

一、引入 在 C 中&#xff0c;我们通常使用函数来完成特定的功能。但有时候&#xff0c;我们需要在一个函数内部定义一个小型的功能块&#xff0c;这时如果单独写一个函数会显得繁琐。C11 引入了 Lambda 函数&#xff0c;它是一种匿名函数&#xff0c;可以在需要的地方直接定义…

OpenCV 基础模块 Python 版

OpenCV 基础模块权威指南&#xff08;Python 版&#xff09; 一、模块全景图 plaintext OpenCV 架构 (v4.x) ├─ 核心层 │ ├─ core&#xff1a;基础数据结构与操作&#xff08;Mat/Scalar/Point&#xff09; │ └─ imgproc&#xff1a;图像处理流水线&#xff08;滤…

iStoreOS软路由对硬盘格式化分区(转化ext4)

一、为什么要格式化分区&#xff1f; 格式化硬盘分区是软路由安装或配置过程中的重要步骤&#xff0c;主要用于清除旧数据、优化文件系统、确保系统稳定性和兼容性。 二、通过iStoreOS硬盘格式化步骤 使用场景&#xff1a;Docker迁移到外置移动硬盘为例&#xff0c;考虑兼容现…

打造用户认证系统,构筑信息安全防线

在当今的数字化时代&#xff0c;信息安全和用户隐私保护变得越来越重要。用户身份认证是确保信息安全的第一道防线。通过验证用户身份&#xff0c;可以防止未经授权的访问和数据泄露。它有助于保护用户的个人信息、账户资金和其他敏感数据。此外&#xff0c;用户身份认证还可以…

北京南文观点:品牌如何抢占AI 认知的 “黄金节点“

在算法主导的信息洪流中&#xff0c;品牌正在经历一场隐蔽的认知权争夺战&#xff0c;当用户向ChatGPT咨询"哪家新能源车企技术最可靠"时&#xff0c;AI调取的知识图谱数据源将直接决定品牌认知排序。南文乐园科技文化&#xff08;北京&#xff09;有限公司&#xff…

音视频系列——Websockets接口封装为Http接口

模型服务示例&#xff1a;实时语音转文本服务 本示例展示一个支持双协议&#xff08;WebSocket流式接口HTTP同步接口&#xff09;的语音转文本模型服务&#xff0c;并提供将WebSocket接口封装为HTTP接口的代码实现。 一、服务架构设计 #mermaid-svg-nw0dMZ4uKfS4vGZR {font-fa…

Axure项目实战:智慧城市APP(一)(动态面板、拖动效果)

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;智慧城市APP便民服务平台 主要内容&#xff1a;完整智慧APP原型设计 应用场景&#xff1a;各类政务型、B端APP均可参考 案例展示&#xff1a;&…

MySQL 入门大全:数据类型

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

Java 记忆链表,LinkedList 的升级版

文章目录 记忆链表 MemoryLinkedList实战源代码 众所周知&#xff0c;ArrayList 和 LinkedList 是 Java 集合中两个基本的数据结构&#xff0c;对应数据结构理论中的数组和链表。但在这两个数据结构&#xff0c;开发者们通常使用 ArrayList&#xff0c;而不使用 LinkedList。JD…

《白帽子讲 Web 安全》之开发语言安全深度解读

目录 引言 1.PHP 安全 1.1变量覆盖 1.2空字节问题 1.3弱类型 1.4反序列化 1.5安全配置 2Java 安全 2.1Security Manager 2.2反射 2.3反序列化 3Python 安全 3.1反序列化 3.2代码保护 4.JavaScript 安全 4.1第三方 JavaScript 资源 4.2JavaScript 框架 5.Node.…

鸿蒙HarmonyOS NEXT应用崩溃分析及修复

鸿蒙HarmonyOS NEXT应用崩溃分析及修复 如何保证应用的健壮性&#xff0c;其中一个指标就是看崩溃率&#xff0c;如何降低崩溃率&#xff0c;就需要知道存在哪些崩溃&#xff0c;然后对症下药&#xff0c;解决崩溃。那么鸿蒙应用中存在哪些崩溃类型呢&#xff1f;又改如何解决…

分析K8S中Node状态为`NotReady`问题

在Kubernetes&#xff08;k8s&#xff09;集群中&#xff0c;Node状态为NotReady通常意味着节点上存在某些问题&#xff0c;下面为你分析正常情况下节点应运行的容器以及解决NotReady状态的方法。 正常情况下Node节点应运行的容器 1. kubelet kubelet是节点上的核心组件&…

第六届机电一体化技术与智能制造国际学术会议(ICMTIM 2025)

重要信息 4月11-13日 南京江北新区工业大学亚朵酒店 www.icmtim.org&#xff08;点击了解参会投稿等&#xff09; 简介 由南京工业大学主办&#xff0c;南京工业大学电气工程与控制科学学院、中国矿业大学、黑龙江大学、江苏省自动化学会承办的第六届机电一体化技术…

INT202 Complexity of Algroithms 算法的复杂度 Pt.2 Search Algorithm 搜索算法

文章目录 1.树的数据结构1.1 有序数据(Ordered Data)1.1.1 有序字典&#xff08;Ordered Dictonary&#xff09;1.1.1.1 排序表&#xff08;Sorted Tables&#xff09; 1.2 二分查找&#xff08;Binary Search&#xff09;1.2.1 二分查找的时间复杂度 1.3 二叉搜索树&#xff0…

【AVRCP】蓝牙链路控制器(LC)与AVRCP互操作性要求深度解析

目录 一 、Link Controller&#xff08;LC&#xff09;概述 1.1 LC的定义与功能 1.2 LC在蓝牙技术中的重要性 二、Link Controller&#xff08;LC&#xff09;互操作性要求 2.1 互操作性要求概述 2.2 物理层互操作性要求 2.3 链路管理互操作性要求 2.4 其他互操作性要求…

高级背景抠图工具(python)

这是一个专业的图像背景处理工具,基于Python开发,主要功能包括:1. 智能背景去除 - 使用rembg库的深度学习模型自动识别并移除图片背景。 2. 背景自定义 - 支持纯色背景替换,保留透明通道(Alpha通道)。3. 高级参数调节 - 提供5种专业级图像处理参数。4. 实时预览 - 双窗口…

如何设计外贸邮件开发信主题

开发信是打开客户大门的第一步&#xff0c;而邮件主题则是决定客户是否打开邮件的关键。一个吸引人的主题不仅能提高打开率&#xff0c;还能为后续沟通打下良好基础。 一、突出价值和利益 邮件主题要直接传达收件人能从中获得的价值和利益&#xff0c;引起他们的兴趣和关注。…

wordpress表单插件CF7调用方式

Contact Form 7(CF7)是WordPress中非常流行的表单插件&#xff0c;以下是其常见的调用方式&#xff1a; 通过短代码调用 在页面或文章编辑器中添加&#xff1a;完成表单设置后&#xff0c;复制表单对应的短代码&#xff0c;然后在需要显示表单的页面或文章的编辑器中直接粘贴…

快速入手-基于Django的主子表间操作mysql(五)

1、如果该表中存在外键&#xff0c;结合实际业务情况&#xff0c;那可以这么写&#xff1a; 2、针对特殊的字典类型&#xff0c;可以这么定义 3、获取元组中的字典值和子表中的value值方法 4、对应的前端页面写法