算法基础之哈希表

news2025/1/23 10:29:46

大家好,这里是教授.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数组就会进行扩容。

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

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

相关文章

视频号视频提取器有那些?免费版可以下载视频号视频吗?

在网络上,确实存在多种工具和公众号用于下载视频号内容。今天就说说免费的视频提取器有那些? 视频号提取器工具中常见的有公众号和软件。这些工具通常可以帮助用户从微信视频号平台下载视频内容。 但请注意,使用这些工具可能需要考虑版权和法…

【记录】打印|用浏览器生成证件照打印PDF,打印在任意尺寸的纸上(简单无损!)

以前我打印证件照的时候,我总是在网上找在线证件照转换或者别的什么。但是我今天突然就琢磨了一下,用 PDF 打印应该也可以直接打印出来,然后就琢磨出来了,这么一条路大家可以参考一下。我觉得比在线转换成一张 a4 纸要方便的多&am…

南卡、韶音、Cleer、漫步者开放式耳机好用吗?最强开放式耳机对比揭秘!

在挑选开放式耳机时,个人经验和实际需求应当优先考虑,而非盲目追随潮流或品牌效应。投资耳机前务必慎重,毕竟高价值商品若无法退换,难免造成遗憾。为了帮助大家做出更加明智的决策,我亲自出资购买并测试了市面上多款主…

【Java】Hutool发送邮件功能

目录 开通qq邮箱的stmp实战pom.xmlapplication.ymlcontrollerservice实体类辅助类 需要实现一个通过邮箱找回密码的功能 正常来说,找回密码的验证码,一般来说,都是通过手机号来找回的居多,那为什么会有通过邮箱找回的方式该说不说…

壁纸取图小程序源码系统 可植入广告 低成本搭建 带完整的安装代码包以及搭建教程

系统概述 本壁纸取图小程序源码系统是一套基于微信小程序框架的完整解决方案,旨在为开发者提供一套高效、稳定、易用的壁纸资源管理与分发平台。系统采用模块化设计,具有良好的扩展性和可维护性,同时支持多种广告形式,为开发者提…

“JS逆向 | Python爬虫 | 动态cookie如何破~”

案例目标 目标网址:aHR0cHMlM0EvL21hdGNoLnl1YW5yZW54dWUuY29tL21hdGNoLzI= 本题目标:提取全部 5 页发布日热度的值,计算所有值的加和,并提交答案 常规 JavaScript 逆向思路 JavaScript 逆向工程通常分为以下三步: 寻找入口:逆向工程的核心在于找出加密参数的生成方式。…

【设计模式】结构型-组合模式

前言 在软件开发中,设计模式是一种被广泛应用的解决问题的方法论。其中,结构性设计模式是一类特别重要的模式,它们用于处理类或对象之间的组合关系,其中之一就是组合模式。组合模式允许客户端统一对待单个对象和对象的组合&#…

实习面试题(答案自敲)、

1、为什么要重写equals方法,为什么重写了equals方法后,就必须重写hashcode方法,为什么要有hashcode方法,你能介绍一下hashcode方法吗? equals方法默认是比较内存地址;为了实现内容比较,我们需要…

RF自动化框架-环境搭建

一、RobotFrame框架简介 (1)RobotFramework简称:RF框架,Robotframework, 采用PO设计模式(page objeck, 页面即对象,将一个实现过程分成不同层次,其实就是一个分层与封装的模式) (2…

一键设置常用纸张和页面边距-Word插件-大珩助手

Word大珩助手是一款功能丰富的Office Word插件,旨在提高用户在处理文档时的效率。它具有多种实用的功能,能够帮助用户轻松修改、优化和管理Word文件,从而打造出专业而精美的文档。 【新功能】常用纸张和常用边距 1、一键设定符合中国人常用…

非递归实现快排排序及归并排序(尾篇)

1.快速排序(双指针实现) 2.非递归实现快排 3.递归实现归并排序 4.非递归实现归并排序 5.总代码 1.快速排序(双指针实现) 俩有个指针一前一后的排放着,cur先走并且去找比kye对应值小的数组值,一旦找到后…

我国液碱产量逐渐增长 行业集中度有望不断提升

我国液碱产量逐渐增长 行业集中度有望不断提升 液碱是由氢氧化钠(NaOH)、氢氧化钾(KOH)等化合物以及水组成的一种碱性化合物。液碱的相对分子质量为40.00,密度为1.318g/cm,在常温常压下多表现为一种无色、无…

萨科微的“Slkor”和金航标“Kinghelm”

宋仕强说,我国的科学研究和先进技术,与先进国家相比还有差距,这一点还体现在社会生产效率和人均GDP上面。我们只有抓住科技进步的风口如人工智能(AI),再加上公司内部的研发和管理等环节的微创新&#xff0c…

ai怎么导出jpg?让我告诉你答案【详】

在设计和创意工作中,Adobe Illustrator(AI)是一款不可或缺的工具。然而,当我们将设计作品导出为JPG格式时,可能会遇到一些问题。ai怎么导出jpg?如何确保导出的JPG图片保持高质量?接下来&#xf…

原子阿波罗STM32F429程序的控制器改为STM32F407

以前,学习原子的探索者开发板,有STM32F407ZGT6开发板,现在想学习阿波罗开发板,但手头没有F429开发板,于是,想把STM32F429芯片替换为STM32F407芯片,本以为没有什么难度,但是替换后发下…

Mysql:通过一张表里的父子级,递归查询并且分组分级

表:gc_jzst_single_base 需求:要求返回这张表里符合条件的数据,且有父子级关系的,展示为同一组且分级,给后续业务调用 代码 WITH RECURSIVE t1 AS (SELECTsingle_id,old_build_single_id,single_name,bulid_code,1 A…

ArcGIS中几个好用的空间分析工具

ArcGIS是一款经典的GIS应用,其空间分析能力很强,有着丰富的空间分析工具。今天,我们一起来了解几个好用的空间分析工具的功用及操作。 注:演示版本为ArcMap10.4.1 1.方向分布(标准差椭圆) 路径&#xff…

三.网络编程套接字_TCP

一.序言 在上一章中,我们已经实现了用udp来实现网络编程,这一节我们用tcp来实现网络编程,通过对比两者编写过程的区别,来加深对udp,tcp的理解! (两者其实差别不大!有了udp的基础,学习起来tcp会…

MongoDB~存储引擎了解

存储引擎 存储引擎是一个数据库的核心,主要负责内存、磁盘里数据的管理和维护。 MongoBD的优势,在于其数据模型定义的灵活性、以及可拓展性。但不要忽略,其存储引擎也是插件式的存在,支持不同类型的存储引擎,使用不同…

C++学习笔记(22)——多态

目录 [TOC](目录) 比喻与理解1. 多态的概念2. 多态的定义及实现2.1多态的构成条件2.2 虚函数2.3虚函数的重写2.3.1 虚函数重写的两个例外:1. 协变(基类与派生类虚函数返回值类型不同)2. 析构函数的重写(基类与派生类析构函数的名字不同) 2.4 C11 override 和 final2…