如何解决哈希冲突?

news2024/9/24 13:14:22

目录

1. 链接法

2. 开放寻址法

2.1. 线性探测

2.2. 二次探测

2.3. 双重哈希

3. 再哈希法

4. 哈希桶扩容

5.方法比较 

5.1. 链接法

5.2. 开放寻址法

5.3. 再哈希法

5.4. 哈希桶扩容

哈希表就是通过散列函数将键映射到定值,简单来说就是一个键对应一个值。

而通过散列函数映射时将两个键映射到了同一个值,即这两个键将被哈希表映射到同一个位置,这种情况就被称为哈希冲突。

解决哈希冲突通过有四种方法:

  • 链接法
  • 开放寻址法
  • 再哈希法
  • 哈希桶扩容

1. 链接法

每个哈希表的槽位维护一个链表或其他数据结构,当多个元素被哈希到同一个槽位时,它们会被放在这个槽位的链表中。查找时会遍历链表,插入时也会直接加到链表中。

假设我们有一个哈希表,哈希函数将键值映射到以下槽位:

  • 0: [5, 15]
  • 1: []
  • 2: [2]
  • 3: []
  • 4: [4]

当我们插入键值 5 和 15 时,它们都被映射到槽位 0。因此,它们会形成一个链表:

槽位 0: [5 -> 15]
槽位 1: []
槽位 2: [2]
槽位 3: []
槽位 4: [4]

2. 开放寻址法

当发生冲突时,算法会寻找下一个可用的槽位。常见的探查方式有线性探查、二次探查和双重哈希等。这种方法不使用额外的存储结构,而是在哈希表内部处理所有元素。开放寻址法的几种常见探测方法确实包括线性探测、二次探测和双重散列。以下是每种方法的详细说明和示例:

2.1. 线性探测

在发生冲突时,线性探测会逐个检查后续的槽位,直到找到一个空槽。例如:

假设哈希函数为 h(k) = k % 5

  • 插入 1 → 槽位 1(成功)
  • 插入 6 → 槽位 1(冲突),检查 2(成功)
  • 插入 11 → 槽位 1(冲突),2(冲突),3(成功)

最终哈希表:

槽位 0: []
槽位 1: [1]
槽位 2: [6]
槽位 3: [11]
槽位 4: []

2.2. 二次探测

二次探测在发生冲突时采用平方递增的方式查找空槽。例如:

哈希函数仍然假设是 h(k) = k % 5

  • 插入 1 → 槽位 1(成功)
  • 插入 6 → 槽位 1(冲突),检查 1^2 → 2(成功)
  • 插入 11 → 槽位 1(冲突),检查 1^2(冲突),2^2 → 4(成功)

最终哈希表:

槽位 0: []
槽位 1: [1]
槽位 2: []
槽位 3: []
槽位 4: [6]

2.3. 双重哈希

双重散列使用第二个哈希函数来决定步长,以解决冲突。例如:

假设第一个哈希函数 h1(k) = k % 5,第二个哈希函数 h2(k) = 1 + (k % 4)

  • 插入 1 → 槽位 1(成功)
  • 插入 6 → 槽位 1(冲突),步长 h2(6) = 1 + (6 % 4) = 3,检查 1 + 3 = 4(成功)
  • 插入 11 → 槽位 1(冲突),步长 h2(11) = 1 + (11 % 4) = 3,检查 1 + 3 = 4(冲突),再检查 4 + 3 = 2(成功)

最终哈希表:

槽位 0: []
槽位 1: [1]
槽位 2: [11]
槽位 3: []
槽位 4: [6]

3. 再哈希法

在发生冲突后,可以使用另一个哈希函数对该元素进行再哈希,找到一个新的槽位。

使用初始哈希函数 h1(k) = k % 5,当插入 10 时:

  • h1(10) = 0(槽位 0 已占用)
  • 使用新的哈希函数 h2(k) = (k / 5) % 5,计算:
    • h2(10) = 2(槽位 2 已占用)
  • 再次使用 h1 计算:
    • h1(10 + 1) = 1(槽位 1 已占用)
    • h1(10 + 2) = 3(放入槽位 3

最终哈希表如下:

槽位 0: [0]
槽位 1: [1]
槽位 2: [2]
槽位 3: [10]
槽位 4: [4]

4. 哈希桶扩容

如果哈希表的负载因子超过某个阈值,可以增加哈希表的大小,并重新计算所有元素的哈希值并重新分配到新的槽位。这有助于减少冲突并提高性能。

哈希表的负载因子是一个衡量哈希表填充程度的重要指标,通常用公式表示为:

负载因子 = 哈希表中的元素数量 / 哈希表的槽位总数

负载因子的意义:

  • 高负载因子:当负载因子接近或超过 1 时,表示哈希表的槽位几乎被填满,可能导致更多的哈希冲突,从而影响查找、插入和删除的性能。
  • 低负载因子:负载因子较低时,哈希表的空槽较多,冲突较少,性能较好,但会导致内存浪费。

负载因子的调整:

通常,当负载因子超过某个设定的阈值(例如 0.7 或 0.75),就会进行扩容。扩容时,哈希表的槽位数量增加,所有元素需要重新哈希并放入新的槽位中。

假设哈希表的大小为 5,当前负载因子超过 0.7,我们决定扩容到 10。在扩容时,所有元素的哈希值需要重新计算:

  • 原哈希表:
槽位 0: [0]
槽位 1: [1]
槽位 2: [2]
槽位 3: [3]
槽位 4: [4]
  • 扩容后,哈希函数改为 h(k) = k % 10,插入后的哈希表:
槽位 0: []
槽位 1: [1]
槽位 2: [2]
槽位 3: [3]
槽位 4: [4]
槽位 5: [5]
槽位 6: []
槽位 7: []
槽位 8: []
槽位 9: []

5.方法比较 

5.1. 链接法

优点:

  • 容易实现,简单明了。
  • 动态性好,可以存储任意数量的元素,只受限于内存。
  • 插入和删除操作较快,不需要重新哈希。

缺点:

  • 在某些情况下,链表可能会很长,导致查找性能下降。如果链表过长,可能导致性能接近于线性查找。
  • 需要额外的内存来存储链表节点。

5.2. 开放寻址法

优点:

  • 所有元素都存储在哈希表内部,节省了额外的内存。
  • 不需要额外的链表,查找时不需要遍历。

缺点:

  • 哈希表的负载因子需要控制在较低水平,通常小于 0.7,否则性能显著下降。
  • 在频繁冲突的情况下,查找效率会下降,且可能需要进行多次探测。
  • 删除操作复杂,可能导致“探测链”的问题,影响后续查找性能。

5.3. 再哈希法

优点:

  • 通过使用不同的哈希函数,能有效地减少冲突。
  • 可与其他方法结合使用,灵活性高。

缺点:

  • 需要额外的计算和存储开销,可能导致性能下降。
  • 在大量元素插入时,可能需要频繁地进行哈希计算。

5.4. 哈希桶扩容

优点:

  • 通过扩容可以有效降低负载因子,从而减少冲突。
  • 能够保持较高的性能,特别是在处理大量数据时。

缺点:

  • 扩容过程可能需要遍历整个哈希表,重新计算哈希值,导致短时间内性能下降。
  • 增加了内存的使用和管理复杂度。

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

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

相关文章

R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析

随机森林作为一种集成学习方法,在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性,随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中,使用Bootstrap抽样生成不同的训练集&#xff…

LeetCode 每日一题 ---- 【2207. 字符串中最多数目的子序列】

LeetCode 每日一题 ---- 【2207. 字符串中最多数目的子序列】 2207.字符串中最多数目的子序列方法:贪心 一次遍历 2207.字符串中最多数目的子序列 方法:贪心 一次遍历 从题意中可以看出来,对于 pattern.charAt(0) 一定是插入到最左侧是最优…

什么是SSL证书?它能保护你的网络安全!

相信大家在浏览网页时经常会看到一些网址前面有个“小锁”图标,它代表的网站是安全的,而这背后的秘密就是SSL证书。那SSL证书到底是什么?它有什么用呢? 什么是SSL证书? SSL证书的全称是Secure Sockets Layer证书&…

php发送邮箱教程:如何实现邮件发送功能?

php发送邮箱性能优化策略?怎么使用PHPMail发送邮箱? 无论是用户注册验证、密码重置,还是系统通知,邮件发送都是不可或缺的一部分。AokSend将详细介绍如何使用PHP实现邮件发送功能,帮助开发者快速掌握这一技能。 php发…

高效驱动,掌控动力:TB67H400AFNG 马达驱动器

在如今智能设备和自动化应用领域中,驱动器的性能直接决定了系统的可靠性与效率。东芝的TB67H400AFNG有刷直流马达驱动器凭借其卓越的性能,成为众多行业解决方案中的关键部件。无论是工业控制、自动化设备还是消费类电子产品,TB67H400AFNG都能…

一小时拿下鸿蒙应用开发者高级证书!(二)

鸿蒙应用开发者高级认证,是华为自家研发的硬核操作系统,现在它在市场上的名声也越来越响亮。你手上要是有了鸿蒙的认证小本本,那就等于是掌握了这行里的独门秘籍,找工作的时候,妥妥的加分项。 一个小时刷刷题&#xf…

玩机进阶教程----MTK芯片杂牌机 小品牌机型以及其他mtk设备导出分区的另外一种方法解析

在前面多期博文中都是通过工具来导出分区 制作线刷包的。今天我们以另外一种方法备份系统分区。mtk芯片较多。具体机型适合哪种方法需要自测。多种方法多条思路。遇到机型善用工具。目前一些wifi网卡 点读笔以及有些其他mtk芯片设备。通常分区都较小。可以参考教程 通过教程了…

amr文件怎么转换成mp3?这几种方法超多人在用!

amr文件怎么转换成mp3?AMR音频格式,作为音频领域的一个相对边缘角色,其应用范围相对狭窄,这背后深藏着多重内在限制,首要挑战在于AMR的音质瓶颈,它难以逃脱声音失真与杂音干扰的阴影,这对于追求…

通过企业微信群机器人 发送群消息

1、添加群机器人,复制的webhook地址 2、 public static void main(String[] args) { String reqUrl "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key6xdexxxxxxxxxxxxxxxxxxxxxxxxxxx"; String title "填…

数据结构 - 查找算法

一.查找的概念 二.顺序表查找 特点: 1.记录的数据可以是无序的 2.当数据量较大时,查找效率低,需要依次遍历 /*** description: 顺序表查找算法,从后往前查找* param - a : 要操作的数组的指针* param - k…

OpenCV_自定义线性滤波(filter2D)应用详解

OpenCV filter2D将图像与内核进行卷积,将任意线性滤波器应用于图像。支持就地操作。当孔径部分位于图像之外时,该函数根据指定的边界模式插值异常像素值。 卷积核本质上是一个固定大小的系数数组,数组中的某个元素被作为锚点(一般…

安霸cv22平台移植采坑记录

主要分为3部分: 1.数据输入部分: 1.因原始测试代码只是单张测试图片(测试格式:安霸平台离线转的bin文件),现在的问题是:如何输入数据流?会不会涉及到字节对齐问题,如何…

ROS第六梯:ROS+VSCode+C++消息发布和订阅

第一步:创建ROS工作空间,并在工作空间下创建名为srr_pkg的功能包,具体步骤参考第二章。 第二步:在src下创建publisher.cpp作为发布节点代码文件,创建subscriber.cpp作为订阅节点代码文件: 主要步骤是&#…

这几个方法轻松压缩ppt文件大小,操作起来很简单的压缩PPT方法

这几个方法轻松压缩ppt文件大小。在当今信息化迅速发展的时代,PPT已成为工作和学习中必不可少的工具。然而,随着内容的增加,文件体积常常变得庞大,影响了分享和传输的便利性。过大的文件不仅占用存储空间,还可能导致演…

Nat Med|机器学习+高通量筛选,发现用于治疗胶质母细胞瘤的神经活性药物|顶刊精析·24-09-23

小罗碎碎念 今日顶刊:Nat Med 这篇文章是2024-09-20发表在《Nature Medicine》上的一篇研究型论文,标题为“High-throughput identification of repurposable neuroactive drugs with potent anti-glioblastoma activity”。 先打个提前量,发…

Java刷题知识总结(一)

1.局部变量参与运算前是必须要初始化的,比如下面的代码就会编译出错,提示y必须要初始化。 public static void main(String[] args) {int x 1;int y;int z x y; } 2.ArrayList和Vector主要区别是什么? A Vector与ArrayList一样&#xf…

Win11+cuda11.7+spconv11.7搭建OpenPCdet

这里写自定义目录标题 前面詳細的教程參考:https://blog.csdn.net/xuegreat1/article/details/141892867 懶得寫了,先寫遇到的一些教程外的bug: 上文教程走完后運行demo.py,但是發現沒有裝mayavi庫,直接安裝報錯&#…

【STM32】PWM

一、 PWM 概述 定义 PWM(Pulse Width Modulation), 脉冲宽度调制。 脉冲: 方波, 频率(freq) 宽度: 高电平的宽度, 占空比(duty) ​ 详细波形如下图。 用途 控制灯光的亮度(手机/平…

ASP.NET Core8.0学习笔记(十九)——EF Core DbSet

一、DbSet概述 1.DbSet提供了通过DbContext对表进行查询操作的路径。DbSet对应的属性名称将默认映射为实体T的表名。 2.使用DbSet<T>进行查询的方法&#xff1a; (1)直接在DbContext中创建对应的DbSet<T>属性 (2)使用DbSet DbContext.Set<T>方法操作数据表。…

红外图像绝缘子识别数据集

红外图像绝缘子识别数据集&#xff0c;数据集一共919张图片&#xff0c;标注为voc格式&#xff0c;可以转yolo格式 数据集名称 红外图像绝缘子识别数据集 (Infrared Insulator Recognition Dataset, IIRD) 数据集描述 IIRD是一个专为电气工程领域设计的小规模红外图像数据集…