Java集合(九)哈希冲突及解决哈希冲突的4种方式
Java集合(九)哈希冲突及解决哈希冲突的4种方式
一、哈希冲突
(一)、产生的原因
哈希是通过对数据进行再压缩,提高效率的一种解决方法。但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致经过哈希函数处理后仍然有不同的数据对应相同的哈希值。这时候就产生了哈希冲突。
(二)、因素
- 装填因子(装填因子=数据总数 / 哈希表长);
- 哈希函数;
- 处理冲突的方法。
(三)、解决哈希冲突的4中方式
开放地址法;再哈希法;链地址法(拉链法);公共溢出区法。
二、开放地址法
开放地址法处理冲突的基本原则就是出现冲突后按照一定算法查找一个空位置存放。公式:

其中:Hi为计算出的地址,h(key)为哈希方法,di增量序列1,2,3,...,k(k<= m - 1),m为哈希表的长度。
假设问题:关键码集合为:{38,25,74,63,52,48,55},m = 7,采用除留余数法h(key) = key mod 7,并存储在哈希表中。

(一)、线性探测:依次向后查找

从上图可以看出,38和52存放3号地址冲突,25和74存放4地址冲突,根据集合,可以知道,38先存放在了3,25先存放了4,所以将74和52进行线上探测,根据公式,线上探测74时,取d = 1,探测52时,取d = 5,最终结果如下表:

优点:只要哈希表未被填满,保证能找到一个空地址单元存放有冲突的元素。
缺点:能使第i个哈希地址的同义词存入第i+1个地址,这样本应存入第i+1个哈希地址的元素变成了第i+2个哈希地址的同义词,产生“聚集”现象,降低查找效率。
(二)、二次探测:依次向前后查找,增量为1、2、3的二次方

以上面(一)线上探测74为例,根据公式,取d = 1²,最终结果如下表:

(三)、伪随机探测:随机产生一个增量位移
还是以74为例,根据公式,取d = 29时,最终结果如下表:

(四)、建立哈希表的步骤
1、取数据元素的关键码key,计算其哈希函数值(地址)。若该地址对应的存储 空间还没有被占用,则将该元素存入;否则执行2解决冲突。
2、根据选择的冲突处理方法,计算关键码key的下一个存储地址。若下一个存储地址仍被占用,则继续执行2,直到找到能用的存储地址为止。
三、再哈希法
再哈希法,又叫双哈希法,有多个不同的Hash函数,出现冲突后采用其他的哈希函数计算,直到不再冲突为止。虽然不易发生聚集,但是增加了计算时间。公式:

其中RHi为不同的哈希函数。比如乘余取整法:RH(k)=[b ×(a × k mod 1)] ,还是以上面74为例:设b = 10,a = 0.6180339,根据公式有:RH(74)=[10 ×(0.6180339 × 74 mod 1)] = 7,最终结果如下表:

四、拉链法(链地址法)
将具有相同哈希地址的记录链成一个单链表,m个哈希地址就设m个单链表,,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。
优点:
1、拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
2、由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
3、开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
4、在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。
缺点:
1、指针占用较大空间时,会造成空间浪费,若空间用于增大散列表规模进而提高开放地址法的效率。
假设:关键字集合{47,7,29,11,16,92,22,8,3,50,37,89},m = 11,哈希算法为H(k) = k mod 11,则建表如下图:

(一)、建立哈希表的步骤
1、取数据元素的关键码key,计算其哈希函数值(地址)。若该地址对应的链表为空,则将该元素插入此链表;否则执行2解决冲突。
2、根据选择的冲突处理方法,计算关键码key的下一个存储地址。若该地址对应的链表不为空,则利用链表的前插法或后插法将该元素插入此链表。
(二)、特点
1、非同义词不会冲突,无“聚集”现象;
2、链表上的结点空间动态申请,适用于表长不确定的情况。
五、公共溢出区法
创建哈希表时,将所有产生冲突的的同义词集中放在一个溢出表中。假设哈希函数的值域是[1,m-1],则设哈希表HashTable[0...m-1]为基本表,每个分量存放一个记录,另外设溢出表OverTable[0,v]为溢出表,所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。

例子:关键码集合{26,36,41,38,44,15,68,12,6,51,25},m = 12,哈希函数:H(k)= k mod 12,则哈希表如下:

上图蓝色部分,元素的哈希地址冲突了,此时创建一个溢出表:

Java集合(九)哈希冲突及解决哈希冲突的4种方式的更多相关文章
- Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式
解析:Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式.面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和Out ...
- Java命令行启动jar包更改默认端口以及配置文件的几种方式
Java命令行启动jar包更改默认端口以及配置文件的几种方式 java -jar xxx.jar --server.port=8081 默认如果jar包没有启动文件,可以采用这种方式进行启动 java ...
- Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式
概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...
- 将Java web应用部署到Tomcat 及部署到Tomcat根目录 的三种方式
Tomcat作为Servlet/JSP容器(服务器)挺不错的,开源免费,需要知道的是Tomcat是一个Web服务器,其符合Servlet/JSP规范,但是却没有实现所有JavaEE规范,所以我们还是应 ...
- java客户端验证https连接(忽略证书验证和证书验证两种方式)
首先根据如下操作生成证书,配置springboot https,生成一个简单的https web服务 https://www.cnblogs.com/qq931399960/p/11889349.ht ...
- Java多线程并发01——线程的创建与终止,你会几种方式
本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...
- Java常见重构技巧 - 去除不必要的!=null判断空的5种方式,很少有人知道后两种
常见重构技巧 - 去除不必要的!= 项目中会存在大量判空代码,多么丑陋繁冗!如何避免这种情况?我们是否滥用了判空呢?@pdai 常见重构技巧 - 去除不必要的!= 场景一:null无意义之常规判断空 ...
- java web中日期Date类型在页面中格式化显示的三种方式
一般我们经常需要在将服务器端的Date类型,传到页面进行显示,这就涉及到一个如何格式化显示Date类型的问题,一般我们有三种方式进行: 1)在服务端使用SimpleDateFormat等类格式化成字符 ...
- Java集合(八)哈希表及哈希函数的实现方式
Java集合(八)哈希表及哈希函数的实现方式 一.哈希表 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的 ...
随机推荐
- swipe 滑动操作
1.swipe() 滑动用法 swipe(self, start_x, start_y, end_x, end_y, duration=None) :Args: - start_x - 开始滑动的x坐 ...
- 《Docker从入门到跑路》之存储卷介绍
默认情况下,容器会随着用户删除而消失,包括容器里面的数据.如果我们要对容器里面的数据进行长久保存,就不得不引用存储卷的概念. 在容器中管理数据持久化主要有两种方式:1.数据卷(data volumes ...
- thinkphp5.x系列 RCE总结
Thinkphp MVC开发模式 执行流程: 首先发起请求->开始路由检测->获取pathinfo信息->路由匹配->开始路由解析->获得模块.控制器.操作方法调度信息 ...
- POJ3169(差分约束:转载)
转载自mengxiang000000传送门 Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10278 Ac ...
- 机器学习的hello world——MNIST
MNIST:一个由60000行训练数据集和10000行的测试数据集(机器学习模型设计时必须有一个单独的数据集用于评估模型的性能)组成的数据集. 下载mnist的数据集后,将文件放入C:\Users\m ...
- 玩好百家乐需要掌握些什么技巧和打法?来自ag老玩家的实战经验心得总结
最近很多网友给我留言,说为什么学了很多技巧和打法这个游戏还是玩不好,坦白说,其实bjl想要玩得好,不是说你懂得多少技巧和掌握了多少种打法就可以的了,而是你要懂得如何把这些正确结合去运用,这些我之前都强 ...
- LFU C# 实现
周六早上 做了下力扣的LRU 题目 后面接着看了LFU 缓存 难度提高了不少 首先 先说下 这2着 的差别把 LRU :最近 最少使用算法(Least Recently Used).LRU 是 ...
- asp.net mvc entityframework sql server 迁移至 mysql方法以及遇到的问题
背景: 我原来的项目是asp.net mvc5 + entityframework 6.4 for sql server(localdb,sql server),现在需要把数据库切换成mysql,理论 ...
- git使用-忽略文件更新的几种方法
有几种情况我们不希望本地文件在 git 里面得到更新. 一.情况:始终不需要git跟踪本地的一些文件 方法:使用.gitignore文件忽略 解释: 使用git init操作创建git控制管理之后,默 ...
- 谈谈DDD
从战略到战术,领域驱动设计(Domain Driven Design,DDD)给出了诸多关于软件架构.设计.建模与编码的方法和模式,以用于应对业务复杂度.然而,许多开发人员对于 DDD 的价值仍然心存 ...