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集合(八)哈希表及哈希函数的实现方式 一.哈希表 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的 ...
随机推荐
- 使用python实现模拟掷骰子数据分析
Data:2020/4/8 主题:模拟实现掷骰子数据分析 编译环境:pycharm 库:pygal 说明: code 1:创建一个掷骰子类对象,类方法获得掷骰子随机数1-6,默认6个面,模拟20次将结 ...
- centos8-django项目部署 nginx+uwsgi
1.虚拟环境virtualenv安装 1.安装virtualenv pip3 install virtualenv 2.创建目录,把项目文件传过来 mkdir My cd My 3.创建独立运行环境- ...
- 【Hadoop离线基础总结】oozie调度shell脚本
目录 1.解压官方提供的调度案例 2.创建工作目录 3.拷贝任务模板到工作目录当中去 4.随意准备一个shell脚本 5.修改模板下的配置文件 6.上传调度任务到hdfs上面去 7.执行调度任务 1. ...
- 【Linux基础总结】Linux基本环境
Linux基本环境 对Linux的基础认识 虚拟机进入终端: [root@hadoop-senior Desktop] # 用户名 主机名 所在目录名称 #:表示当前用户属于root用户,超级管理员用 ...
- 02JAVA基础-运算符及选择语句
一.运算符 1.算数运算符 算数运算符 备注 + 可以用作拼接 - * / 整数相除得整数,需要获得小数,需一方为浮点数 % 取余数 ++ 自增 -- 自减 扩展(1) 对于++和--的扩展(以++为 ...
- AXI总线slave模式下接收数据---verilog代码
AXI总线slave模式下接收数据---verilog代码 `timescale 1ns / 1ps ///////////////////////////////////////////////// ...
- Loadrunner中遇到Failed to connect to server[10061] connection refused错误
(1)run-time setting/browser emulation中,将simulate a new user on each iteration 选项去掉(默认是选中的). 重新运行一切正 ...
- Abp领域事件(EventBus)源码解析
Abp中使用EventBus来解耦领域中的业务逻辑,也是订阅-发布模式的一种实现.简单来说就是,当我触发一个事件,注册了这个事件的处理器就会被找到并执行. 先看看整体代码结构 其中Entities文件 ...
- My sql的知识点 不足点请指点谢谢
My SQL:(关系数据库) 数据库能够能够干吗? 1. :存储大量的信息,方便检索和访问 2. :保持数据信息的一致,完整 3. : 共享和安全 4. : 通过组合分析,产生新的有用 ...
- python之文件操作模块(os和shutil)
1.os.name #操作系统类型 如果是posix,说明系统是liunx.Unix或Mac OS X,如果是nt,就是windows2.os.enviro #操作系统中定义的环境变量3.os.e ...