「数据结构」哈希表1:基本概念

🎇个人主页:Ice_Sugar_7
🎇所属专栏:Java数据结构
🎇欢迎点赞收藏加关注哦!

基本概念

  • 🍉哈希表
  • 🍉哈希冲突
    • 🍌负载因子调节
    • 🍌解决哈希冲突
      • 🥝1. 闭散列法
      • 🥝2. 开散列法(哈希桶)

🍉哈希表

哈希表是一种数据结构,它使用哈希函数将键映射到数组中的一个位置(即将元素的存储位置和它的key之间建立映射关系)

  • 在存储一个键值对时,哈希函数根据key计算出一个索引(哈希地址),然后将键值对存储在对应的索引位置上

举个例子:

数据集合{1,7,6,4,5,9}
哈希函数设置为:hash(key) = key % capacity(capacity为存储元素底层空间的大小)

那我们可以推出每个元素存储的位置为
在这里插入图片描述

  • 在搜索元素时,对元素的key进行同样的计算,把求得的函数值当做元素的存储位置,在哈希表中取这个位置的元素进行比较,若key相等,则搜索成功

因为通过哈希函数计算得到的索引可以直接指向元素所在的位置,所以在理想情况下,查找、插入和删除操作的时间复杂度可以达到O(1)


🍉哈希冲突

不同的关键字通过相同的哈希函数计算出相同的哈希地址,该种现象称为哈希冲突

造成哈希冲突的原因之一是:哈希函数设计不够合理
我们在设计哈希函数时,应遵循:

  1. 哈希函数的定义域需要包括所有待存储的关键码
  2. 计算出来的哈希地址能均匀分布在整个空间中
  3. 哈希函数应该比较简单

🍌负载因子调节

哈希表载荷因子定义为 α = 填入表中的元素个数 / 哈希表长度
α越大,表明填入表中的元素越多,发生冲突的可能性越大
当α超过一定阈值时,会触发哈希表的扩容操作

在Java中,HashMap默认负载因子是0.75,0.75是一个被认为在时间和空间效率上做了平衡的经验值,它既保证了空间的有效利用,又尽量减少了冲突的发生,是一个相对较优的选择。

负载因子和冲突率的关系粗略演示:
在这里插入图片描述

我们可以通过降低负载因子来降低冲突率,因为哈希表中已有的关键字个数是不可变的,那么我们能调整的就只有哈希表中的数组的大小
注意:哈希表扩容后,需要重新计算里面的关键字的哈希地址

🍌解决哈希冲突

解决哈希冲突两种常见的方法是:闭散列开散列

🥝1. 闭散列法

也叫开放定址法,发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置的“下一个”空位置中
那怎么找空位置呢?

  • 线性探测
    从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止
    比如对于刚才上面的例子:
    在这里插入图片描述
    如果要插入44,那它会和4产生冲突,采用线性探测解决冲突的话,那就会插入到下标为8这个空位置在这里插入图片描述

线性探测的缺陷是产生冲突的数据堆积在一块,这与其找下一个空位置有关系,因为找空位置的方式就是挨着往后逐个去找。如果表中只填入4,而接下来要填入44,14,24,34一系列数字的话:
在这里插入图片描述
采用二次探测可以避免这个问题

  • 二次探测
    二次探测通过下面的公式算出要插入哪个空位置
    在这里插入图片描述

比如对于上面的例子,使用二次探测解决冲突后得到:
在这里插入图片描述

🥝2. 开散列法(哈希桶)

又叫链地址法、开链法
先用哈希函数算出每个关键码的哈希地址,具有相同地址的关键码归于同一子集合,每个子集合称为一个,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中
在这里插入图片描述
从这个图可以看出:开散列中每个桶放的都是发生哈希冲突的元素

  • 在一些哈希表的实现中,当哈希桶中的链表长度超过一定阈值时,可能会将链表转换为红黑树。因为当链表长度较长时,查找、插入和删除操作的时间复杂度会变得较高,而红黑树的时间复杂度相对较低,将链表转换为红黑树可以提高哈希表的性能
  • 在JDK 8中的HashMap实现中,当链表长度超过8个元素时,会将链表转换为红黑树

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

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

相关文章

Python 错误及其解决方法

Python 是一种易于学习的编程语言,但初学者在学习和使用 Python 的过程中难免会遇到一些错误。以下是一些常见的 Python 错误及其解决方法: 1. 语法错误(SyntaxError): python # 错误示例 print("Hello, World!…

sqli-labs-master靶场训练笔记(54-65|决战紫禁之巓)

2024.2.5 level-54 1、先判断类型和闭合类型 ?id1/0 #正常 证明不是数字型 ?id1 #错误 ?id1 -- a #正常 判断是 闭合 2、 判断列数 这里需要运气,但是根据前面50多关的经验直接猜测是3列 ?id-1 union select 1,2,3 -- a 3、爆表名&#xf…

[ai笔记1] 借着“ai春晚”开个场

1 文思ai笔记-新的开始 今天是2024年2月29日,也是传统农历的除夕夜。早起在ai圈看到一个比较新奇的消息,ai春晚今日举办,竟然有一点小小的激动。这些年确实好久没看过春晚了,自己对于春晚的映像还停留在“白云黑土”、“今天&…

《21天精通IPv4 to IPv6》第9天:云和容器中的IPv6——如何在云端☁️容器中实现IPv4到IPv6?

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

备份还原实际操作

备份还原实际操作 前言 根据达梦文档整理。 一、工具介绍 工具联机/脱机工具应用场景disql联机1️⃣数据库备份2️⃣归档备份3️⃣表空间备份与还原4️⃣表备份与还原dmrman脱机1️⃣数据库备份、还原和恢复2️⃣脱机还原表空间3️⃣归档的备份、还原和修复manager联机对应…

联想DP510、DP520、DP515打印机恢复出厂和自定义纸张方法

联想DP510、DP520、DP515恢复出厂设置方法 一、按下打印方式键,同时开机,直至打印头动作停止时松手; 二、水平装入 A4 纸,打印机自动调入并开始打印,若打印机将纸退出,将纸放平重新装入; 三、…

Idea Git Review插件

idea git plugin 添加了一些常用的小插件 可以右键打开git bash窗口 可以右键选中文字点击baidu fanyi 可以通过搜索git用户名 指定开始时间查询某个版本自己提交的所有代码文件 可以通过点击蓝色行数,跳转到指定的改动代码块 资源地址: git-pl…

Elasticsearch:混合搜索是 GenAI 应用的未来

在这个竞争激烈的人工智能时代,自动化和数据为王。 从庞大的存储库中有效地自动化搜索和检索信息的过程的能力变得至关重要。 随着技术的进步,信息检索方法也在不断进步,从而导致了各种搜索机制的发展。 随着生成式人工智能模型成为吸引力的中…

MATLAB知识点:矩阵的除法

​讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 节选自第3章 3.4.2 算术运算 下面我们再来介绍矩阵的除法。事…

Python自学之路:从入门到精通

一、引言 Python,作为最受欢迎的编程语言之一,不仅语法简洁易懂,而且应用领域广泛,从数据科学、机器学习、网络开发到自动化脚本编写等,无所不能。对于初学者来说,如何系统地自学Python可能会是一个挑战。…

Linux操作系统下安装消息中间件RabbitMQ_00000

下载 在官网下载Linux版RabbitMQ安装文件。 erlang-21.3-1.el7.x86_64.rpm rabbitmq-server-3.8.8-1.el7.noarch.rpm 安装 1、将文件上传至Linux系统中。 上传到/usr/local/software目录下(如果没有software目录,则创建。)。 2、安装文件&…

PySpark(四)PySpark SQL、Catalyst优化器、Spark SQL的执行流程、Spark新特性

目录 PySpark SQL 基础 SparkSession对象 DataFrame入门 DataFrame构建 DataFrame代码风格 DSL SQL SparkSQL Shuffle 分区数目 DataFrame数据写出 Spark UDF Catalyst优化器 Spark SQL的执行流程 Spark新特性 自适应查询(SparkSQL) 动态合并 动态调整Join策略 …