算法基础之哈希表

大家好,这里是教授.F

什么是哈希表:

      哈希表其实就是数组的pro版本。数组有下标,每个下标对应着一个值。哈希表也类似,哈希表有很多哈希值,然后每一个哈希值都会对应着一个值。就是这样:hash(key)

哈希表的要求:

        1.key必须是不变的。

这点非常重要。

所谓不可变类型,就是说这个对象一旦创建,它的值就不能再改变了。比如 Java 中的 String, Integer 等类型,一旦创建了这些对象,你就只能读取它的值,而不能再修改它的值了。

作为对比,Java 中的 ArrayList、LinkedList 这些对象,它们创建出来之后,可以往里面随意增删元素,所以它们是可变类型。

因此,你可以把 String 对象作为哈希表的 key,但不能把 ArrayList 对象作为哈希表的 key。

 如果使用ArrayList对象作为哈希表的key,那经常性的改变会导致每次计算 hashCode 都要遍历整个数组,复杂度是 O(N),这样就会导致哈希表的增删查改操作的复杂度退化成 O(N)

哈希函数:

        我们先来讨论一下,关于哈希表中key的取值我们想怎么来搞定???

我们想怎么根据key来得到一个唯一值。首先在java中每一个对象都有int hashCode()这个方法。在我们不重写hashCode()这个方法的时候,该方法就会返回对象的内存地址,恰恰我们就想拿到一个唯一的数值来进行转换。所以唯一值思路我们已经确定。但还有一个问题:hashCode()的类型是int类型,int可是有负数的啊。索引可不兴是负数啊!如果只是这样想 :

int h = key.hashCode();
h = Math.abs(h);

也是不行。因为int类型得负数 2 ^31 ,正数是 2 ^ 31 - 1。会发现数据溢出了。

               我们可以通过位运算来进行操作,将最高位得符号去掉。这样不仅能解决问题,而且位运算比算术运算快得多。

        

h = h & 0x7fffffff;
h 是一个整数变量,它代表某个哈希值。
0x7fffffff 是一个十六进制常量,
对应的二进制表示是 0111 1111 1111 1111 1111 1111 1111 1111。
它的最高位(即最左边的一位)是 0,其余位都是 1。
& 是按位与(AND)操作符,它将两个操作数的对应位进行逻辑与运算。
只有当两个操作数的对应位都是 1 时,结果位才是 1,否则结果位为 0。

但还有一个问题,就是这个 hashCode 一般都很大,我们需要把它映射成 table 数组的合法索引。

这是使用的技巧是取模。

 h % table.length;
这样就保证了在table数组的范围内
但是考虑性能,我们可以通过位运算来替代:
要将取模运算 h % table.length 用位运算来代替,
通常要求 table.length 是 2 的幂次方。这是因为取模运算可以用位运算来模拟,
而且当除数是 2 的幂次方时,这种替代特别高效。

假设 table.length 是 2 的幂次方,
比如 table.length = 2^k,那么 h % table.length 
可以等价地表示为 h & (table.length - 1)。

具体的替代方法如下:

将 table.length 减去 1,得到一个二进制全是 1 的数,
例如,当 table.length = 16 时,table.length - 1 = 15,
其二进制表示为 0000 0000 0000 1111。
这样得到的结果就是一个与原数相比,位数更低的数字。
比如对于 table.length = 16,它相当于对 h 的低 4 位进行了保留,而将高位清零。
这个结果就等价于对 h 取模 table.length,
因为对于任何整数 x,x % 2^k 的结果就是 x 的低 k 位的值。

 哈希冲突:

        现实中,我们通过这样计算哈希值,但是往往会造成哈希值相同,也就是哈希冲突,所以对于哈希冲突我们还要有解决方案:

以上就是出现情况的解决方案。

扩容和负载因子:

        为什么要引入这个东西,这个东西是什么???

首先上面出现的哈希冲突的解决方案会降低性能。

拉链法:就是在同一个位置使用链表进行串联,在查找的时候,时间复杂度为:O(K)K 是这个链表的长度。

线性探查法:就是如果算出的哈希值位置已经被占了。我们就继续往后面寻找位置,直到找到一个空位置。时间复杂度为:O(K)K 为连续探查的次数。

当哈希表有太多的key-value时,很容易出现冲突的情况,所以我们需要进行扩容。

负载因子(Load Factor)是指哈希表(Hash Table)中已存储元素数量与哈希表容量之比。

负载因子的计算公式也很简单,就是 size / table.length。其中 size 是哈希表里面的 key-value 对的数量,table.length 是哈希表底层数组的容量。

当哈希表内元素数量达到负载因子的时候,table数组就会进行扩容。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

这个高考作文满分的极客,想和你聊聊新媒体写作

计育韬 曾为上海市高考作文满分考生 微信官方 SVG AttributeName 开发者 新榜 500 强运营人 复旦大学青年智库讲师 浙江传媒学院客座导师 上海团市委新媒体顾问 上海市金山区青联副主席 文案能力,从来就不是一蹴而就的。今天,来和大家聊聊当年我的…

端午档新片速递《谈判专家》领衔,每日影视作品推荐❗❗❗多部佳作待映

每日影视作品推荐一、新片速递《谈判专家》上映时间:2024年端午档预售情况:已开启预售,并有望成为该档期的票房冠军备注:据猫眼专业版数据,该片备受期待 《我才不要和你做朋友呢》上映时间:2024年端午档期预…

CSS函数: 实现数据限阈的数字函数

CSS函数中提供了几个比较实用的数字函数,它可以帮助我们实现一定的数学计算功能。常见的数字函数目前提供了五个:calc()、max()、min()和clamp()函数。其基本实现功能如下: calc():允许在声明 CSS 属性值时执行一些计算。max()&a…

智能推荐算法应用:如何提升淘宝在线扭蛋机用户购物体验

在淘宝的在线扭蛋机平台上,用户的购物体验至关重要。为了提升这一体验,我们引入了智能推荐算法,帮助用户发现他们可能感兴趣的扭蛋产品。这一技术的应用不仅提高了用户的购物效率,还大大增强了用户的购物乐趣。 一、智能推荐算法…

Python语法详解module2(运算符、表达式、流程控制)

目录 一、运算符1. 算术运算符(Arithmetic Operators)2. 比较运算符(Comparison Operators)3. 赋值运算符(Assignment Operators)4. 逻辑运算符(Logical Operators)5. 位运算符&…

cocos creator3.7版本拖拽事件处理

前言:网上能找到的资料都太落后了,导致哥们用AI去写,全是瞎B写,版本都不对。贴点实际有用的。别老捣鼓你那破convertToNodeSpaceAR或者convertToNodeSpace了。 核心代码 touch.getDeltaX() touch.getDeltaY() 在cocoscreator3…

Python | 刷题日记

1.海伦公式求三角形的面积 area根号下&#xff08;p(p-a)(p-b&#xff09;(p-c)) p是周长的一半 2.随机生成一个整数 import random xrandom.randint(0,9)#随机生成0到9之间的一个数 yeval(input("please input:")) if xy:print("bingo") elif x<y:pri…

sql 查询 不满足 (一个教师编号 的角色 (role =‘2‘or(role=‘1‘and role =‘0‘)) )

sql 查询 不满足 &#xff08;一个教师编号 的角色 &#xff08;role 2’or&#xff08;role1’and role ‘0’&#xff09;&#xff09; &#xff09; 准备 一个 teacher 表 和数据 表 teacher 和数据 -- ---------------------------- -- Table structure for teacher -- …

[Algorithm][动态规划][回文串问题][分割回文串 II][最长回文子序列][让字符串成为回文串的最少插入次数]详细讲解

目录 1.分割回文串 II1.题目链接2.算法原理详解3.代码实现 2.最长回文子序列1.题目链接2.算法原理详解3.代码实现 3.让字符串成为回文串的最少插入次数1.题目链接2.算法原理详解3.代码实现 1.分割回文串 II 1.题目链接 分割回文串 II 2.算法原理详解 思路&#xff1a; 确定状…

现代操作系统(第四版)课后习题-4.文件系统

四、文件系统 1.给出文件/etc/passwd的五种不同的路径名 在Unix和类Unix系统中&#xff0c;/etc/passwd 是系统中所有用户账户信息的标准文件。 绝对路径&#xff1a;直接使用文件的绝对路径来访问。 /etc/passwd使用环境变量&#xff1a;如果设置了环境变量指向某个目录&…

Java中的接口与抽象类:区别与联系

Java中的接口与抽象类&#xff1a;区别与联系 在Java中&#xff0c;interface&#xff08;接口&#xff09;和abstract class&#xff08;抽象类&#xff09;是两种重要的抽象类型&#xff0c;用于定义对象的抽象行为和结构。虽然Java 8之后接口引入了默认方法和静态方法&…

磁场定向控制转速环PI调节器参数整定

前言 本章节采用工程设计的方法&#xff0c;推导转速环PI调节器参数的计算公式&#xff0c;由此来设计永磁同步电机磁场定向控制的转速外环PI调节器参数&#xff0c;并通过Matlab/Simulink对设计的PI调节器进行Bode图分析。 一、调节器的工程设计方法 要实现调节器的工程设计…

kube-promethesu新增k8s组件监控(etcd\kube-controller-manage\kube-scheduler)

我们的k8s集群是二进制部署 一、prometheus添加自定义监控与告警&#xff08;etcd&#xff09; 1、步骤及注意事项&#xff08;前提&#xff0c;部署参考部署篇&#xff09; 1.1 一般etcd集群会开启HTTPS认证&#xff0c;因此访问etcd需要对应的证书 1.2 使用证书创建etcd的…

[next.js]pwa缓存

配置Next.js (v14 App Router模式) 使其支持PWA缓存&#xff0c;配置server worker和mainfest.json&#xff0c;让项目支持离线访问和可安装。 安装依赖next-pwa npm i next-pwa配置next.config.js const path require(path);const withPWAInit require(next-pwa);// 判断…

俄罗斯人有哪些常用的口头禅,柯桥零基础俄语培训

Хватит! 够了&#xff01; -Хватит, не стоит больше шуметь! 够了, 不要再吵了! -Это тебя не касается! 这与你无关&#xff01; Блин! 靠&#xff01; Блин这个词绝对是俄罗斯人最爱用的口语表达之一&#xff0c;…

给快高考的儿子的一封信:关于选择计算机专业

亲爱的儿子&#xff0c; 你好&#xff01; 时间过得真快&#xff0c;转眼间你就要高考了&#xff0c;这不仅是你人生中的一个重要时刻&#xff0c;也是我们全家都非常关注的节点。妈妈告诉我&#xff0c;你对计算机专业很感兴趣&#xff0c;希望我能给你一些建议。我很高兴听…

阿里云邮件推送配置教程:有哪些关键步骤?

阿里云邮件推送服务如何配置&#xff1f;如何设置SMTP服务器&#xff1f; 阿里云作为国内领先的云服务提供商&#xff0c;其邮件推送服务具有高效、稳定和可靠的特点&#xff0c;因此备受企业青睐。Aok将介绍阿里云邮件推送配置教程的关键步骤&#xff0c;并简要提及AokSend的…

重要经济数据对行情的影响有多大?

金融市场上的消息非常多&#xff0c;可以来自不同国家、不同大型企业&#xff0c;也可以由不同机构统计公布&#xff0c;甚至是各国政府或中央银行的发表。在宏观经济层面上&#xff0c;所有政经消息都属于金融市场的风险事件&#xff0c;大多能引起市场波动&#xff0c;因此投…

LC 26删除有序数组中的重复项

去重题&#xff0c;双指针&#xff0c;&#xff0c;因为题干说原地删除&#xff0c;且nums其余元素不重要。一个cur记录当前不重复的数应该插在第几位了&#xff0c;for循环里的i相当于是第二个指针&#xff08;右指针&#xff09;&#xff0c;遍历数组来找不重复的元素 class …

2024/6/5(页面静态化,熔断降级,降级处理,ES搜索实例,课程信息同步,认证授权,单点登录,Spring Security,OAuth2,授权模式)

elasticsearch目录下执行docker-compose up -d 完美解决 执行下面这个命令 curl -XDELETE localhost:9200/.kibana_task_manager_7.12.1_001 重启es和kibana服务