一.哈希表简介

非哈希表的特点:关键字在表中的位置和它自检不存在一个确定的关系,查找的过程为给定值一次和各个关系自进行比较,查找的效率取决于给定值进行比较的次数。
哈希表的特点:关键字在表中位置和它自检存在一种确定的关系。
哈希函数:一般情况下,需要在关键字与它在表中的存储位置之间建立一个函数关系,以(key)作为关键字为key的记录在表中的位置,通常称这个函数f(key)为哈希函数。
hash:翻译为”散列表“,就是把任意长度的输入,通过散列算法,变成固定长度输出,该输出结果是散列值。
这种转换是一种压缩映射,散列表的空间通常小鱼输入的空间,不同的输入可能会散列成相同的输出,所以不能从散列表来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到固定长度的消息摘要函数。
hash冲突:就是根据key即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经有人先来了。就是说这个地方要挤一挤啦。这就是所谓的hash冲突啦

二.哈希函数处理冲突的方法

1)开放定址法:

这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:

Hi=(H(key)+di)% m i=1,2,…,n

其中H(key)为哈希函数,m 为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下三种:

线性探测再散列

dii=1,2,3,…,m-1

这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

二次探测再散列

di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )

这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。

伪随机探测再散列

di=伪随机数序列。

具体实现时,应建立一个伪随机数发生器,(如i=(i+p) % m),并给定一个随机数做起点。

例如,已知哈希表长度m=11,哈希函数为:H(key)= key % 11,则H(47)=3,H(26)=4,H(60)=5,假设下一个关键字为69,则H(69)=3,与47冲突。

如果用线性探测再散列处理冲突,下一个哈希地址为H1=(3 + 1)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 + 2)% 11 = 5,还是冲突,继续找下一个哈希地址为H3=(3 + 3)% 11 = 6,此时不再冲突,将69填入5号单元。

如果用二次探测再散列处理冲突,下一个哈希地址为H1=(3 + 12)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 - 12)% 11 = 2,此时不再冲突,将69填入2号单元。

如果用伪随机探测再散列处理冲突,且伪随机数序列为:2,5,9,……..,则下一个哈希地址为H1=(3 + 2)% 11 = 5,仍然冲突,再找下一个哈希地址为H2=(3 + 5)% 11 = 8,此时不再冲突,将69填入8号单元。

2) 再哈希法

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

Hi=RH1(key) i=1,2,…,k

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

3)链地址法

这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

4)建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。

优缺点

开放散列表(open hashing)/拉链法(针对桶链结构
1)优点:①对于记录总数频繁可变的情况,处理的比较好(也就是避免了动态调整的开销)由于记录存储在结点中,而结点是动态分配,不会造成内存的浪费,所以尤其适合那种记录本身尺寸(size)很大的情况,因为此时指针的开销可以忽略不计了删除记录时,比较方便,直接通过指针操作即可
2)缺点: ①存储的记录是随机分布在内存中的,这样在查询记录时,相比结构紧凑的数据类型(比如数组),哈希表的跳转访问会带来额外的时间开销 ②如果所有的 key-value 对是可以提前预知,并之后不会发生变化时(即不允许插入和删除),可以人为创建一个不会产生冲突的完美哈希函数(perfect hash function),此时封闭散列的性能将远高于开放散列 ③由于使用指针,记录不容易进行序列化(serialize)操作
封闭散列(closed hashing)/ 开放定址法
1)优点: ①记录更容易进行序列化(serialize)操作 ②如果记录总数可以预知,可以创建完美哈希函数,此时处理数据的效率是非常高的

2)缺点: ①存储记录的数目不能超过桶数组的长度,如果超过就需要扩容,而扩容会导致某次操作的时间成本飙升,这在实时或者交互式应用中可能会是一个严重的缺陷 ②使用探测序列,有可能其计算的时间成本过高,导致哈希表的处理性能降低 ③由于记录是存放在桶数组中的,而桶数组必然存在空槽,所以当记录本身尺寸(size)很大并且记录总数规模很大时,空槽占用的空间会导致明显的内存浪费 ④删除记录时,比较麻烦。比如需要删除记录a,记录b是在a之后插入桶数组的,但是和记录a有冲突,是通过探测序列再次跳转找到的地址,所以如果直接删除a,a的位置变为空槽,而空槽是查询记录失败的终止条件,这样会导致记录b在a的位置重新插入数据前不可见,所以不能直接删除a,而是设置删除标记。这就需要额外的空间和操作。

Hash冲突的四种解决办法的更多相关文章

  1. [转]hash冲突的四种办法

    原文地址:http://blog.csdn.net/qq_27093465/article/details/52269862 一)哈希表简介 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的 ...

  2. Hash冲突的几种解决方法

    1. 开放定值法: 也叫再散列法,当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突 ...

  3. Too many open files的四种解决办法【华为云技术分享】

    [摘要] Too many open files有四种可能:一 单个进程打开文件句柄数过多,二 操作系统打开的文件句柄数过多,三 systemd对该进程进行了限制,四 inotify达到上限. 领导见 ...

  4. Too many open files的四种解决办法

    [摘要] Too many open files有四种可能:一 单个进程打开文件句柄数过多,二 操作系统打开的文件句柄数过多,三 systemd对该进程进行了限制,四 inotify达到上限. 领导见 ...

  5. MYSQL导入中文数据乱码的四种解决办法

    方法一:通过增加参数 --default-character-set = utf8 解决乱码问题 方法一:通过增加参数 --default-character-set = utf8 解决乱码问题 my ...

  6. SourceTreet提交时显示remote: Incorrect username or password ( access token )(4种解决办法)

    引言 我因为第一次安装Sources Tree的时候进行破解时(跳过安装时的登录),因为操作失误造成了好多bug,导致Sources Tree不论提交,拉取,获取,都会报remote: Incorre ...

  7. java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...

  8. Unity多单位战斗寻路问题的一种解决办法

    Unity多单位战斗寻路问题的一种解决办法 Unity提供了NavMesh 导航组件   NavMesh是在实践中通用性最好的一种导航方式,但是Unity的实现并没有完全提供一个开放自由的API. 主 ...

  9. 64位Ubuntu运行32位程序时报文件不存在(No such file or Directory)的一种解决办法

    尝试在64位Ubuntu下面运行32位程序时, 一直说 文件不存在(No such file or directory), 我只想说++. 你tm说个文件格式不正确不就好了? 非得说个文件不存在! 真 ...

随机推荐

  1. 边学边体验django

    django菜鸟入门连接:http://www.runoob.com/django/django-template.html 安装以及Demo里面都有. 我边学边在电脑上演示,然后发现一些和实际不一样 ...

  2. java监测硬盘空间大小

    package com.zuidaima.util.file; import java.io.File; public class FreeDiskSpace { public static void ...

  3. 用chrome console实现自动化操作网页

    因为chrome console只能访问当前页的上下文(以及chrome扩展的上下文),无法访问其他标签页面的上下文,所以局限性较大,仅适用于一些较简单的操作 经实践,可以在chrome的一个标签页的 ...

  4. Asp.Net跨平台 Jexus 5.8.1 独立版

    在Linux上运行ASP.NET网站或WebApi的传统步骤是,先安装libgdiplus,再安装mono,然后安装Jexus.在这个过程中,虽然安装Jexus是挺简便的一件事,但是安装mono就相对 ...

  5. Sketch教程

    去年夏天开始用Sketch,觉得它放Dock里闪亮亮的很好看,当时笑称是男盆友送我的第一颗小钻石噗哈哈.所以那段时间几乎刷遍了所有关于 Sketch 的网站.文章.教程,之后又在自学设计,因为想和更多 ...

  6. Java 类加载

    类的生命周期 类的生命周期是从class文件到类加载 开始.类卸载结束. https://gitbook.cn/books/5cb844a55f75cc777e4c2320/index.html

  7. linux系统安装Memcache

    Linux系统安装memcached 首先要先安装libevent库. centos  下执行 yum install libevent libevent-devel 查看memcached 是否已经 ...

  8. 学PHP应注意的问题与知识点

    编出一手好代码,这个是需要你在平时开发中日积月累的,平时如果你有注意到以下的那些代码的编码,那么祝贺你,你在技能提升这方面已经垫下了一些基础,编写出一手好代码,说白了就是你特么注意到性能这块的问题,代 ...

  9. mongodb 数据更新命令、操作符

    一.Mongodb数据更新命令 Mongodb更新有两个命令:update.save. 1.1update命令 update命令格式: db.collection.update(criteria,ob ...

  10. Jenkins 自动化部署上线

    转载于互联网 jenkins自动化部署项目,通过jenkins 部署来节省运维时间,不需要手动cp上线及版本发布 Jenkins 自动化部署上线 Jenkins Jenkins 自动化部署上线一.Je ...