IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 哈希表原理 -> 正文阅读

[数据结构与算法]哈希表原理

作者:一棵梧桐木

在了解golang的map之前,我们需要了解哈希这个概念。

哈希表,又称散列表(Hash table),是根据键(key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将所需查询的数据映射到表中的一个位置让人访问,这加快了查找速度。这个映射函数称为散列函数,存放记录的数组称作散列表。

1、特点

一个优秀的哈希函数应该包含以下特性:

  • 均匀性:一个好的哈希函数应该在其输出范围内尽可能均匀地映射,也就是说,应以大致相同的概率生成输出范围内的每个哈希值。
  • 高效率:哈希效率要高,即使很长的输入参数也能快速计算出哈希值。
  • 单向性:哈希过程必须是确定性的,这意味着对于给定的输入值,它必须始终生成相同的哈希值。
  • 雪崩效应:微小的输入值变化也会让输出值发生巨大的变化。
  • 不可逆:从哈希函数的输出值不可反向推导出原始的数据。

2、哈希冲突

由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,因此总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突。

3、解决哈希冲突的方法

解决哈希冲突的方法一般有:开放定址法、链地址法(拉链法)、再哈希法、建立公共溢出区等方法。

而我们这里主要介绍开放地址法和拉链法。

3.1、拉链法

链接地址法的思路是将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除主要在同义词链表中进行。链表法适用于经常进行插入和删除的情况。

哈希表原理

3.2、开放地址法

从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元。然后把发生冲突的元素存入到该单元的一种方法。开放定址法需要的表长度要大于等于所需要存放的元素。

在开放寻址法中解决冲突的方法有:线性探测法、平方探测法、双散列函数探测法。

开放定址法的缺点在于删除元素的时候不能真的删除,否则会引起查找错误,只能做一个特殊标记。只到有下个元素插入才能真正删除该元素。

3.2.1、线性探测法

线性探查法是开放定址法中最简单的冲突处理方法,它从发生冲突的单元起,依次判断下一个单元是否为空,当达到最后一个单元时,再从表首依次判断。直到碰到空闲的单元或者探查完全部单元为止。

设Hash(key)表示关键字key的哈希值,表示哈希表的槽位数(哈希表的大小)。

线性探测法可以表示为:

  • 如果Hash(x)%M已经有数据,则尝试(Hash(x)+1)%M
  • 如果(Hash(x)+1)%M有数据,则尝试(Hash(x)+2)%M
  • 如果(Hash(x)+2)%M有数据,则尝试(Hash(x)+3)%M

同样以哈希函数H(key)=key MOD 7(除数取余法)对一组元素[50,700,76,85,92,73,101]进行映射。

哈希表原理

其中,empty代表槽位为空,occupied代表槽位已被占(后续映射到该槽,则需要线性向下继续探测),而lazy delete则代表将槽位里面的数据清除,并不释放存储空间。

3.2.2、平方探测法

平方探查法即是发生冲突时,用发生冲突的单元d[i], 加上 12、 22等。即d[i] + 12,d[i] + 22, d[i] + 32…直到找到空闲单元。 在实际操作中,平方探查法不能探查到全部剩余的单元。不过在实际应用中,能探查到一半单元也就可以了。若探查到一半单元仍找不到一个空闲单元,表明此散列表太满,应该重新建立。

3.2.3、双散列函数探测法

这种方法使用两个散列函数hl和h2。

其中hl和前面的h一样,以关键字为自变量,产生一个0至m-l之间的数作为散列地址;

h2也以关键字为自变量,产生一个l至m-1之间的、并和m互素的数(即m不能被该数整除)作为探查序列的地址增量(即步长),探查序列的步长值是固定值l.

对于平方探查法,探查序列的步长值是探查次数i的两倍减l;

对于双散列函数探查法,其探查序列的步长值是同一关键字的另一散列函数的值。

4、小结

哈希桶:所有哈希值组成哈希空间

装载因子:表示哈希表中元素的填满程度。
计算方式:装载因子=填入哈希表中的元素个数/哈希表的长度。
装载因子越大,填入的元素越多,空间利用率越高,发生哈希冲突的几率变大。
装载因子越小,填入的元素越少,空间利用率越低,但空间浪费多,而且会提高扩容操作的次数。

开放地址法

只用数组一种数据结构就可完成存储,继承了数组的优点,对CPU缓存友好,易于序列化操作。

但是它对内存的利用率不如链地址法,且发生冲突时代价更高。当数据量明确、装载因子小,适合采用开放寻址法。

链地址法

1、处理冲突简单,且无堆积现象

2、由于拉链法中各链表上的节点空间在需要时创建,不必像开放地址法事先申请好足够的内存,因此对内存使用率较高,适合造表前无法确定表长的情况

3、对装载因子的容忍度较高,适合存储大对象、大数据量的哈希表

4、删除结点的操作易于实现,只要简单地删去链表上相应的结点即可。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-09 11:55:23  更:2021-12-09 11:58:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/10 2:41:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码