【java基础 10】hash算法冲突解决方法
导读:今天看了java里面关于hashmap的相关源码(看了java6和java7),尤其是resize、transfer、put、get这几个方法,突然明白了,为什么我之前考数据结构死活考不过,就差那么一点点。答:代码积累太少了!这段时间,看了java的源码、演变过程等,被虐的很惨,但是,很开心! 本篇文章,主要介绍解决hash算法冲突的方法
一、基本概念
散列表:
hash:a mixture of meat, potatoes, and vegetables cut into small pieces and baked or fried
简单说来,hash就是一组碎片的集合!所以,我们常说的hash函数,即散列函数指:数据元素的键值和存储位置之间建立的对应关系H !而用键值通过散列函数获取存储位置的这种存储方式构造的存储结构称为散列表(hash table),这一映射过程称为散列。如果选定了某个散列函数H及相应的散列表L,则对每个数据元素X,函数值H(X.key)就是X在散列表L中的存储位置,这个存储位置也称为散列地址(可以理解为hashcode)
PS:在理想情况下,应用的散列函数可以使每个键值与散列地址是意义对应的,但在实际应用中,这种情况很少或几乎不会出现。经常出现的问题有:冲突
冲突:如果有散列函数H和键值A、B(A不等于B),但是H(A)=H(B)即算出的散列地址是一样的,这种现象称为冲突! ——A、B为相对于H的同义词
二、常用的解决hash冲突的方法
2.1,开放地址法
当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止,常用的方法有:线性探测法、二次探测法(解决线性探测的堆积问题)、随机探测法(和二次探测原理一致,不一样的是:二次探测以定值跳跃,而随机探测的散列地址跳跃长度是不定值)
缺点:1,删除工作很困难,假如要从哈希表 HT 中删除一个记录,应将这个记录所在位置置为空,但我们只能标上已被删除的标记,否则,将会影响以后的查找。
2,不易探测到整个散列表的所有空间(线性探测法除外,但线性探测会出现堆积)
2.2,拉链法(链地址法)
将所有关键字为同义词的结点链接在同一个单链表中,【例】设有 m = 5 , H(K) = K mod 5 ,关键字值序例 5 , 21 , 17 , 9 , 15 , 36 , 41 , 24 ,按外链地址法所建立的哈希表如下图所示:
优点:1,处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短。
2,由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况。
3,更易于实现插入和删除
缺点:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。
2.3,多重散列法(再哈希法)
这种方法是同时构造多个不同的哈希函数:
Hi=RH1(key) i=1,2,…,k
当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生“堆积”,但增加了计算时间。
2.4,公共溢出区法
散列表由两个一维数组组成,一个称为基本表,它实际上就是一个散列表。另外一个称为溢出表。插入首先在基本表上进行,假如发生冲突,则将同义词存入溢出表。这样,可以保证基本表不会发生“堆积”
PS:基本表是不会发生堆积了,那溢出表呢?当进行查找时,查找到溢出表,这是不是又开启了新一轮的冲突解决?
三、总结
再次看了一遍书,对于hash函数有了更深一层的理解。尤其是看了一些代码之后,发现自己真的很low!如上述介绍,综合而言,开放地址法、再哈希法、公共溢出区法都无可避免的多次冲突或堆积的解决或者消费了大量的时间,所以,选择链地址法是相对而言最合适的。
现在,终于解决了一个自己之前的疑惑,为什么hashmap或者hashtable会选择用一个数组和链表的形式来实现?我那时候就在想,为啥不是全用数组呢?我只想到了把数据放进去,却没有去想怎么把数据拿出来用、综合效率问题!
【java基础 10】hash算法冲突解决方法的更多相关文章
- Hash算法冲突解决方法分析
采用开放定址法处理散列表的冲突时,其平均查找长度? 高于链接法处理冲突 低于二分查找 开放定址法:一旦发生冲突,就去寻找下一个空的散列地址,只要散列地址够大,空的地址总会找到 链地址法: 一旦发生冲 ...
- [转]Hash碰撞冲突解决方法总结
我们知道,对象Hash的前提是实现equals()和hashCode()两个方法,那么HashCode()的作用就是保证对象返回唯一hash值,但当两个对象计算值一样时,这就发生了碰撞冲突.如下将介绍 ...
- Java基础系列-equals方法和hashCode方法
原创文章,转载请标注出处:<Java基础系列-equals方法和hashCode方法> 概述 equals方法和hashCode方法都是有Object类定义的. publi ...
- Java实现一致性Hash算法
Java代码实现了一致性Hash算法,并加入虚拟节点.,具体代码为: package com.baijob.commonTools; import java.util.Collection; im ...
- IIS上虚拟站点的web.config与主站点的web.config冲突解决方法 分类: ASP.NET 2015-06-15 14:07 60人阅读 评论(0) 收藏
IIS上在主站点下搭建虚拟目录后,子站点中的<system.web>节点与主站点的<system.web>冲突解决方法: 在主站点的<system.web>上一级添 ...
- IIS上虚拟目录下站点的web.config与根站点的web.config冲突解决方法
IIS7.5上在站点下部署虚拟目录,访问虚拟目录下的项目提示与父节点配置冲突.,节点与的<system.web>节点与主站点的<system.web>冲突解决方法: 在站点下的 ...
- java.lang.OutOfMemoryError: PermGen space及其解决方法(转载)
java.lang.OutOfMemoryError: PermGen space及其解决方法 分类: java2007-09-11 12:34 162242人阅读 评论(51) 收藏 举报 gene ...
- Ubuntu Hash Sum mismatch 解决方法
有时候通过校园网对Ubuntu14.04进行更新时,会出现以下问题: W: Failed to fetch http://xxxxxxx Hash Sum mismatch 解决方法:打开搜索 → ...
- 转:git合并冲突解决方法
git合并冲突解决方法 1.git merge冲突了,根据提示找到冲突的文件,解决冲突 如果文件有冲突,那么会有类似的标记 2.修改完之后,执行git add 冲突文件名 3.git commit注意 ...
随机推荐
- 【Linux】使用Cockpit进行主机管理
Cockpit 进行主机监控 官网文档: https://cockpit-project.org/running.html 版本信息 针对Red Hat [root@master ~]# cat /e ...
- MySql中查询语句实现分页功能
import java.util.*;import java.sql.*; public class FruitDao { private Connection conn; private ...
- 从零开发分布式数据库中间件 二、构建MyBatis的读写分离数据库中间件
在上一节 从零开发分布式数据库中间件 一.读写分离的数据库中间件 中,我们讲了如何通过ThreadLocal来指定每次访问的数据源,并通过jdbc的连接方式来切换数据源,那么这一节我们使用我们常用的数 ...
- winhex与磁盘格式与 数据恢复
第一阶段: 熟悉WinHex的使用. n 熟悉磁盘工具的使用. n 利用WinHex查看物理磁盘和逻辑磁盘. n 了解WinHex中相关工具的用法. 以管理员身份运行winhex(以便之后修改) 上方 ...
- WebStorm换主题(护眼)
一.下载喜欢颜色的主题 http://www.phpstorm-themes.com/ 我用的豆沙绿护眼 <scheme name="Solarized Light My" ...
- fckeditor配置详解
使用配置设置: . FCKConfig.CustomConfigurationsPath = '' ; // 自定义配置文件路径和名称 . FCKConfigFCKConfig.EditorAreaC ...
- mysql 特定查询条件下导致的大海捞针
order表: order type gmt_create type 取值: 0,1 其中0非常多,1非常少. 当查询条件里 select * from order where type=0 an ...
- shell脚本,通过传参求斐波那契数列如(0,1,1,2,3,5,8,13..........)
[root@localhost wyb]# cat fibo.sh #!/bin/bash #斐波那契数列 ,,,,,,, > file >> file count=$ for i ...
- javaEE(12)_数据库连接池
一.直接获取数据库连接和通过池获取示意图: 二.编写数据库连接池 1.实现DataSource接口,并实现连接池功能的步骤: •在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加 ...
- windows 使用git上传代码至github
1. 首先创建github账户 2. 创建github项目 3. windows安装git工具 ·下载地址:https://git-for-windows.github.io/ ,下载直接安装即可, ...