【基础知识】什么是哈希冲突?

2023-10-27

1. 什么是哈希表

哈希表(Hash Table)是一种数据结构,它可以快速地在大量数据中查找、插入和删除时数据。哈希表通过使用哈希函数将键(Key)映射到一个位置,然后在该位置存储或查找数据。

哈希函数的作用是,将键转换为一个整数,这个整数通常称为哈希值(Hash Value)。哈希表的范围通常与哈希表的大小相同。当我们插入或查找数据时,首先计算键的哈希值,然后根据哈希值在哈希表中定位数据。

这里有一个简单的例子来说明哈希表的工作原理:
    假设我们有一个哈希表,大小为5,哈希函数为key mod 5。现在我们要插入键值分别为1、3、8和11的数据。
    首先,我们计算每个键的哈希值:1 mod 5 = 1,3 mod 5 = 3,8 mod 5 = 3,11 mod 5 = 1。然后,我们根据哈希值在哈希表中定位数据。键值为1和11的数据被映射到哈希表的第2个位置(下标从0开始),键值为3和8的数据被映射到哈希表的第4个位置。
    由于键值为1和11被映射到同一个位置,因此发生了哈希冲突。此时,我们可以采用链地址法来解决冲突,在第2个位置建立一个链表,将这两个数据依次存储在链表中。


最终,哈希表中的数据存储情况如下:
```
0: 空
1: [1] -> [11]
2: 空
3: [3] -> [8]
4: 空
```


    当我们查找键值为8的数据时,首先计算它的哈希值:8 mod 5 = 3。然后根据哈希值在哈希表中定位数据,在第4个位置找到了一个链表。最后,在链表中查找键值为8的数据,并返回结果。

由于不同的键可能被映射到同一个位置,因此需要采取一些措施来解决哈希冲突。

2. 什么是哈希冲突

哈希冲突(Hash Collision)是指在使用哈希表存储数据时,两个或多个不同的键(Key)被哈希函数映射到同一个位置的情况。这种情况会导致数据的存储和查找变得复杂,因此需要采取一些措施来解决哈希冲突。

3. 解决哈希冲突的方法

1、开放地址法(Open Addressing)

是一种解决哈希冲突的方法,它的基本思想是,当发生哈希冲突时,按照某种规则寻找下一个空闲的位置来存储数据。

常用的开放地址法有线性探测法、二次探测法和双重哈希法。

(1)线性探测法

是指当发生哈希冲突时,从当前位置开始,依次向后查找下一个空闲的位置,或查遍全表。

例如:
    假设我们有一个哈希表,大小为5,哈希函数为key mod 5。当我们插入键值为1、6和11的数据时,它们都会被映射到哈希表的第2个位置(1 mod 5 = 6 mod 5 = 11 mod 5 = 1)。此时,我们可以采用线性探测法来解决冲突。
    首先将键值为1的数据存储在第2个位置,然后从第2个位置开始,依次向后查找下一个空闲的位置。最终,我们找到了第3个位置,并将键值为6的数据存储在那里。同样地,我们再次从第2个位置开始查找,并在第4个位置找到了一个空闲的位置,将键值为11的数据存储在那里。


''
0: 空
1: [1]
2: [6]
3: [11]
4: 空
''

使用线性探测法解决哈希冲突时,查找、插入和删除操作的时间复杂度与哈希表的装载因子成正比。因此,在设计哈希表时,应尽量选择合适的哈希函数和哈希表大小,并合理控制装载因子,以减少冲突的发生。

(2)二次探测法

是指当发生哈希冲突时,从当前位置开始,按照二次函数的规律查找下一个空闲的位置。

这里有一个简单的例子来说明二次探测法的工作原理。
    假设我们有一个哈希表,大小为5,哈希函数为key mod 5。现在我们要插入键值分别为1、3、8和11的数据。我们采用二次探测法来解决哈希冲突。
    首先,我们计算每个键的哈希值:1 mod 5 = 1,3 mod 5 = 3,8 mod 5 = 3,11 mod 5 = 1。然后,我们根据哈希值在哈希表中定位数据。键值为1和11的数据被映射到哈希表的第2个位置(下标从0开始),键值为3和8的数据被映射到哈希表的第4个位置。
    由于键值为1和11被映射到同一个位置,因此发生了哈希冲突。此时,我们可以采用二次探测法来解决冲突,从第2个位置开始,按照二次函数的规律查找下一个空闲的位置。最终,我们找到了第4个位置,并将键值为11的数据存储在那里。
    同样地,由于键值为3和8被映射到同一个位置,因此也发生了哈希冲突。我们采用同样的方法解决冲突,从第4个位置开始,按照二次函数的规律查找下一个空闲的位置。最终,我们找到了第0个位置,并将键值为8的数据存储在那里。

最终,哈希表中的数据存储情况如下:
```
0: [8]
1: [1]
2: 空
3: [3]
4: [11]
```


    当我们查找键值为8的数据时,首先计算它的哈希值:8 mod 5 = 3。然后根据哈希值在哈希表中定位数据,在第4个位置发现没有数据。此时,我们按照二次探测法的规则继续查找,并在第0个位置找到了键值为8的数据。

使用二次探测法解决哈希冲突时,查找、插入和删除操作的时间复杂度与哈希表的装载因子成正比。因此,在设计哈希表时,应尽量选择合适的哈希函数和哈希表大小,并合理控制装载因子,以减少冲突的发生。

(3)双重哈希法

是指当发生哈希冲突时,使用另一个哈希函数计算出下一个空闲的位置。

这里有一个简单的例子来说明双重哈希法的工作原理。
    假设我们有一个哈希表,大小为5,第一个哈希函数为h1(key) = key mod 5,第二个哈希函数为h2(key) = 3 - (key mod 3)。现在我们要插入键值分别为1、3、8和11的数据。我们采用双重哈希法来解决哈希冲突。    首先,我们计算每个键的哈希值:h1(1) = 1 mod 5 = 1,h1(3) = 3 mod 5 = 3,h1(8) = 8 mod 5 = 3,h1(11) = 11 mod 5 = 1。然后,我们根据哈希值在哈希表中定位数据。键值为1和11的数据被映射到哈希表的第2个位置(下标从0开始),键值为3和8的数据被映射到哈希表的第4个位置。
    由于键值为1和11被映射到同一个位置,因此发生了哈希冲突。此时,我们可以采用双重哈希法来解决冲突,使用第二个哈希函数计算出下一个空闲的位置:(1 + h2(11)) mod 5 = (1 + (3 - (11 mod 3))) mod 5 = (1 + (3 - 2)) mod 5 = (2) mod 5 = 2。最终,我们找到了第3个位置,并将键值为11的数据存储在那里。
    同样地,由于键值为3和8被映射到同一个位置,因此也发生了哈希冲突。我们采用同样的方法解决冲突,使用第二个哈希函数计算出下一个空闲的位置:(3 + h2(8)) mod 5 = (3 + (3 - (8 mod 3))) mod 5 = (6) mod 5 = 1。由于第2个位置已经被占用,因此我们继续计算下一个空闲的位置:(3 + h2(8) * h2(8)) mod 5 = (9) mod 5 =4。最终,我们找到了第0个位置,并将键值为8的数据存储在那里。

最终,哈希表中的数据存储情况如下:
```
0: [8]
1: [1]
2: [11]
3: [3]
4: 空
```

当我们查找键值为8的数据时,首先计算它的哈希值:h1(8) = 8 mod

2、链地址法

链地址法是一种处理哈希冲突的方法,它是将所有散列到同一个地址的数据项存储在一个单链表中。这样,当查找某个数据项时,只需要在对应的链表中进行搜索即可。例如,HashMap 在解决存储对象存在 hash 冲突的问题时,采用的就是链地址法,将相同 hash 值的对象以链表的形式进行存储。

3、再哈希法

在发生冲突的时候,再用另一个哈希函数算出哈希值,直到算出的哈希值不同为止。

4、建立公共溢出区

在创建哈希表的同时,再额外创建一个公共溢出区,专门用来存放发生哈希冲突的元素。查找时,先从哈希表查,查不到再去公共溢出区查。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【基础知识】什么是哈希冲突? 的相关文章

  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • Caliburn.Micro - ShowDialog() 如何关闭对话框?

    EDIT 新信息 刚刚设法让记录器工作 老实说 我不知道 cm 有一个 并且在尝试使用时收到此消息TryClose TryClose requires a parent IConductor or a view with a Close m
  • 如何在特定时间以毫秒精度触发 C# 函数?

    我有两台计算机 它们的时间通过 NTP 同步 确保时间仅相差几毫秒 其中一台计算机将通过 TCP 向另一台计算机发送一条消息 以在两台计算机上的未来指定时间启动某个 c 函数 我的问题是 如何在特定时间以毫秒精度 或更好 触发 C 中的函数
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 平滑手绘曲线

    我有一个允许用户绘制曲线的程序 但这些曲线看起来不太好 它们看起来摇摇欲坠 而且是手绘的 所以我想要一种能够自动平滑它们的算法 我知道平滑过程中存在固有的模糊性 因此它不会每次都完美 但这种算法似乎确实存在于多个绘图包中 并且它们工作得很好
  • ContentDialog 未与 UWP 中心对齐

    据我所知 ContentDialog的默认行为应该是使其在 PC 上居中并在移动设备上与顶部对齐 但就我而言 即使在 PC 上我也将其与顶部对齐 但我不明白发生了什么 我正在使用代码隐藏来创建它 这是我正在使用的代码片段 Creates t
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 如何将 Q 格式整数转换为浮点数(反之亦然)?

    我四处搜寻 找不到一个很好的问题来回答这个问题 给定一个整数 使用Q Format https en wikipedia org wiki Q number format 如何将该数字转换为普通浮点类型 反之亦然 如何将浮点类型转换为Q F
  • .NET 5 EF Core SaveChangesAsync 因错误而挂起

    尽管这个问题有很多结果 但没有一个真正给我明确的答案 每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据 例如重复的主键 时 我都会看到以下日志 执行 DbCommand 失败 15 毫秒 我还在 SQ
  • 处理“未找到细胞”。 Excel 中的错误

    我正在使用 Excel VSTO 应用程序并使用以下代码在工作表中查找错误单元格 Excel Range rngTemp Excel Range rngErrorRange Excel Worksheet Sheet1 Excel Work
  • 如何构建一棵与或树?

    我需要一个支持 与 和 或 的树结构 例如 给定一个正则表达式 如ab c d e 我想把它变成一棵树 所以 一开始我们有两个 或 分支 它可以向下ab or c d e 如果你低头ab分支 你得到两个节点 a and b or a其次是b
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • C++ 中是否有与 PHP 的explode() 函数等效的函数? [复制]

    这个问题在这里已经有答案了 可能的重复 在 C 中分割字符串 https stackoverflow com questions 236129 splitting a string in c 在 PHP 中 explode 函数将获取一个字
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • Xcode 7 调试器不会中断内联标头函数

    过去五年我一直在各种 C 项目中使用 Xcode 没有出现这个问题 今天 我打开了一个较旧的项目 大约 2 年前 并尝试通过在该函数中放置一个活动断点来调试头文件中的内联函数 由于某种原因 调试器不会中断此代码 但是 如果我在调用该函数的
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int
  • 如何使用 C# 为 azure devops 变量赋值

    我有 selenium C 测试脚本 可以从浏览器获取令牌 我有两个 azure devops 任务 一个用于执行 selenium 测试 另一个用于执行 API 测试 我想将 selenium 测试获取的令牌传递给 API 测试执行任务

随机推荐

  • [译] APT分析报告:03.OpBlueRaven揭露APT组织Fin7/Carbanak(上)Tirion恶意软件

    这是作者新开的一个专栏 主要翻译国外知名的安全厂商APT报告文章 了解它们的安全技术 学习它们溯源APT组织的方法 希望对您有所帮助 前文分享了钓鱼邮件网址混淆URL逃避检测 这篇文章将介绍APT组织Fin7 Carbanak的Tirion
  • 什么浏览器好用稳定速度快?

    什么浏览器好用稳定速度快 说到浏览器 不知道你们是否有这样的困惑和烦恼 浏览器换了一款又一款 内存大就不说了 体验总是不尽人意 经常弹出一些莫名其妙的资讯 还会出现卡住 奔溃 网页打开不完全 打开速度慢等情况 就拿我最近用的两款360来说吧
  • Nginx+lua实现秒杀系统架构

    能今天做好的事就不要等到明天 以梦为马 学习趁年华 文章目录 前言 一 秒杀业务特点 1 瞬时高并发 2 热点数据 3 读多写少 二 技术难点 1 数据一致性 2 库存超卖 三 秒杀注意事项 1 数据预热 2 请求承载 3 请求拦截 四 微
  • 重新理解Linux交叉编译及编译流程

    参考书籍 1 编译原理 2 嵌入式Linux应用开发 文章目录 一 交叉编译背景 二 gcc和arm linux gcc的常用选项 1 查询gcc帮助 2 常用gcc选项介绍 3 生成一个可执行文件的三种方法 二 交叉编译的四个流程及实例说
  • iOS编程基础-OC(六)-专家级技巧:使用ARC

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第6章 专家级技巧 使用ARC 本章是第一部分的最后一章 本章介绍ARC内存管理中的细微之处 如直接桥接对象使用ARC的方法 6 1 ARC和对象所有权 我们已经知道
  • 快排-java

    快排总结 分区方法 3个while 递归使用排序方法 使用了分治法 挖坑赋值法 package cn com import java util Arrays public class QuickSort public static void
  • 虚拟机上CentOS 7关闭防火墙操作

    虚拟机上CentOS 7关闭防火墙操作 1 首先查看防火墙的状态 使用的命令为 service iptables status 提示 Unit iptables service could not be found 解决方案 还原传统的管理
  • sprintf实例

    include
  • Unity热更新 ILRuntime 从零开始 HelloWorld(二)

    自从我凌晨两点放下喝醉的小姐姐回家写博客之后 小姐姐对我愈发的崇拜了 约我今晚一块学习ILRuntime 带好身份证 我这一想必须要未雨绸缪 安排 选了一个全市最好的网吧 斥巨资通宵5元 请小姐姐一块学习 一起记录下学习内容 这是这一系列文
  • 数字频率计设计

    FPGA教程目录 MATLAB教程目录 设计任务与要求 1 设计任务 设计并实现一个数字频率计 2 基本要求 测频率范围 10Hz 10K Hz 为保证测量精度分为三个频段 10Hz 100 Hz 100Hz 1K Hz 1 K Hz 10
  • lua语言json与table互转,简单方法

    使用方法 1 json转table luaJson json2lua tab 2 table转json luaJson table2json str 这个原理就是是逐个解析字符串 同样可以解析json xml 具体代码如下 这里解析json
  • wayland详解

    简单地说 Wayland是一套display server Wayland compositor 与client间的通信协议 而Weston是Wayland compositor的参考实现 其官网为http wayland freedesk
  • 如何制作网站?如何制作网站教程

    如果公司企业想要知道如何制作网站 那么需要了解一些相关的内容 本文将介绍如何制作网站教程 希望对大家有所帮助 首先我们做好一些准备 域名 建站工具 图文素材 营业执照等资质 步骤一 创建站点 进入建站工具 24 fkw com 后 在工具中
  • 前端Vue自定义精美商品分类组件category 可用于电商应用分类页面

    随着技术的发展 开发的复杂度也越来越高 传统开发方式将一个系统做成了整块应用 经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改 造成牵一发而动全身 通过组件化开发 可以有效实现单独开发 单独维护 而且他们之间可以
  • 贝叶斯分类

    贝叶斯分类 贝叶斯分类是一类分类算法的总称 这类算法均以贝叶斯定理为基础 故统称为贝叶斯分类 本文作为分类算法的第一篇 将首先介绍分类问题 对分类问题进行一个正式的定义 然后 介绍贝叶斯分类算法的基础 贝叶斯定理 最后 通过实例讨论贝叶斯分
  • [Cmake]源码编译安装Cmake

    源码编译安装Cmake 获取cmake软件包 解压并进入软件包目录 执行配置 编译和安装命令 设置环境变量 执行如下命令验证是否安装成功 获取cmake软件包 wget https cmake org files v3 18 cmake 3
  • PTA 7-3 求整数序列中出现次数最多的数 (10 分)

    本题要求统计一个整型序列中出现次数最多的整数及其出现次数 输入格式 输入在一行中给出序列中整数个数N 0
  • ELF文件头结构

    转自 https blog csdn net tangyuesb article details 54630787 ELF文件头结构定义在 usr include elf h 头文件下 ELF文件有32位版本和64位版本 故其头文件结构也有
  • 进度条教程【github.com/cheggaaa/pb】

    进度条 学习目标 学习内容 前置说明 一个简单的进度条案列 多个进度条的联合使用 进度条在文件Copy IO流的运行 学习总结 学习目标 了解进度条运行原理 掌握github com cheggaaa pb第三方依赖的函数 实践一个进度条
  • 【基础知识】什么是哈希冲突?

    1 什么是哈希表 哈希表 Hash Table 是一种数据结构 它可以快速地在大量数据中查找 插入和删除时数据 哈希表通过使用哈希函数将键 Key 映射到一个位置 然后在该位置存储或查找数据 哈希函数的作用是 将键转换为一个整数 这个整数通