哈希碰撞

news/2024/12/29 14:49:07/

一、什么是哈希碰撞

所谓哈希(hash),就是将不同的输入映射成独一无二的、固定长度的值(又称"哈希值")。它是最常见的软件运算之一。如果不同的输入得到了同一个哈希值,就发生了"哈希碰撞"(collision)。

二、哈希碰撞产生原理

举个例子,假设要将某些元素存放在长度length,则其中某一个元素的key值为k,则其哈希值hash的计算公式为:

hash = (k)%length

假设length = 16,那么两个不同元素的key值分别为12和28,那么他们所取得的hash值都等于12,这就造成冲突了。

三、解决方法

1.开放地址法
开放地址法有一个公式:

Hi = H((key)+di) % m (i = 1,2,3,...,k)  (k <= m-1)

其中,m为哈希表的表长,di是产生冲突时的增量序列。
①线性探查法
当didi取值为1,即为线性探查法,每次冲突后,向后移动一个位置。
基本思想
将散列表T[0…m-1]看成是一个循环向量,若初始探查的地址为d(即h(key)=d),则最长的探查序列为:d,d+l,d+2,…,m-1,0,1,…,d-1即:探查时从地址d开始,首先探查T[d],然后依次探查T[d+1],…,直到T[m-1],此后又循环到T[0],T[1],…,直到探查到T[d-1]为止。
探查过程终止于三种情况:
(1)若当前探查的单元为空,则表示查找失败(若是插入则将key写入其中);
(2)若当前探查的单元中含有key,则查找成功,但对于插入意味着失败;
(3)若探查到T[d-1]时仍未发现空单元也未找到key,则无论是查找还是插入均意味着失败(此时表满)。
缺点

  1. 处理溢出需另编程序。
  2. 按上述算法建立起来的哈希表,删除工作非常困难。假如要从哈希表 HT 中删除一个记录,按理应将这个记录所在位置置为空,但我们不能这样做,而只能标上已被删除的标记,否则,将会影响以后的查找。
  3. 线性探测法很容易产生堆聚现象。所谓堆聚现象,就是存入哈希表的记录在表中连成一片。按照线性探测法处理冲突,如果生成哈希地址的连续序列愈长 ( 即不同关键字值的哈希地址相邻在一起愈长 ) ,则当新的记录加入该表时,与这个序列发生冲突的可能性愈大。因此,哈希地址的较长连续序列比较短连续序列生长得快,这就意味着,一旦出现堆聚 ( 伴随着冲突 ) ,就将引起进一步的堆聚。

②线性补偿探测法
将线性探测的步长从 1 改为 Q ,即将上述算法中的 j = (j + 1) % m 改为: j = (j + Q) % m ,而且要求 Q 与 m 是互质的,以便能探测到哈希表中的所有单元。

③随机探测法
将线性探测的步长从常数改为随机数,即令: j = (j + RN) % m ,其中 RN 是一个随机数。在实际程序中应预先用随机数发生器产生一个随机序列,将此序列作为依次探测的步长。这样就能使不同的关键字具有不同的探测次序,从而可以避 免或减少堆聚。基于与线性探测法相同的理由,在线性补偿探测法和随机探测法中,删除一个记录后也要打上删除标记。

2.再哈希法
这种方法是同时构造多个不同的哈希函数:

 Hi=RH1(key)  i=12,…,k

当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

3.链地址法(拉链法)
可以理解为数组+链表,即在一个线性数组里的每一个元素存储一个链表的头结点。例如:, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A。一会后又进来一个键值对B,通过计算其index也等于0,则进行B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C。也就是说数组中存储的是最后插入的元素。
优点:
① 拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
② 由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
③ 开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
④ 在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结 点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在 用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。
缺点:
指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。


http://www.ppmy.cn/news/343590.html

相关文章

分析数据之雷达图

结果图&#xff1a; 步骤分析如图&#xff1a; 极轴就是极坐标系的开始位置&#xff0c;代码中的angles就是极轴转出来的角度 1、明确有几个特征&#xff0c;将圆平均切分 2、每个特征的数据 3、绘图 代码&#xff1a; import matplotlib.pyplot as plt import numpy as n…

R实战| 雷达图(Radar Chart)

R实战| 雷达图(Radar Chart) 雷达图(radar chart)&#xff0c;又称蜘蛛网图(spider plot)&#xff0c;是一种表现多维数据的强弱的图表。它将多个维度的数据量映射到坐标轴上&#xff0c;这些坐标轴起始于同一个圆心点&#xff0c;通常结束于圆周边缘&#xff0c;将同一组的点使…

echarts 雷达图

Echarts 常用各类图表模板配置 注意&#xff1a; 这里主要就是基于各类图表&#xff0c;更多的使用 Echarts 的各类配置项&#xff1b; 以下代码都可以复制到 Echarts 官网&#xff0c;直接预览&#xff1b; 图标模板目录 Echarts 常用各类图表模板配置一、雷达图二、环形图三…

线形图雷达图

目录 销售统计( sales )-线形图 销售统计( sales )-切换效果 渠道分布(channel)-雷达图 销售统计( sales )-线形图 需求1&#xff1a; 修改折线图大小&#xff0c;显示边框设置颜色&#xff1a;#012f4a&#xff0c;并且显示刻度标签。 // 设置网格样式grid: { top: 20%,left…

使用oracle遇到问题笔记

一、oracle还原到不同版本的oracle数据库报错和解决办法 产生&#xff1a;执行imp导入dmp备份文件时报错 错误内容&#xff1a;导入失败提示&#xff1a;“不是有效的导出文件, 标头验证失败”解决方法 解决办法&#xff1a;http://t.csdn.cn/pJyhc

echarts----雷达图

实现步骤&#xff1a; * 寻找官方的类似示例&#xff0c;给予分析&#xff0c;并引入到HTML页面中 * 按照需求来定制它 第一步&#xff1a; 参考类似实例 (function() {// 1. 实例化对象var myChart echarts.init(document.querySelector(".radar"));// 2.指定配…

”六边形战士”雷达图原来是这样画出来的

"六边形战士"雷达图是怎样画出来的 大家认识这张图吧&#xff01; ​ 图片来源于网络 乒乓球大佬马龙无论是从力量、速度、技巧、发球、防守、经验六个方面都是边框撑爆&#xff0c;不得不说&#xff0c;在日本乒乓球选手面前马龙就是神一样的存在啊&#xff0c;就…

图像Haar小波变换

说起小波变换就需要提起傅里叶变换。傅里叶变换就是把波进行分解&#xff0c;可以认为任意一个周期波都可以有足够多的正弦&#xff08;余弦&#xff09;波组成&#xff0c;这里足够多的正弦波对应的频率不同&#xff0c;把这些足够的正弦波放在频域中&#xff0c;就是傅里叶变…