2016-08-21 22:13 6303人阅读 评论(10) 收藏 举报
 分类:
java 提高篇(24)  面试题收录(10) 

版权声明:觉得此文有用的,不嫌麻烦的,就留个言呐,或者点个赞呐(额,就是文章底部的“顶”啦),要是嫌弃麻烦呢,也麻烦点个赞嘛,要是实在不想点赞呢,也不是不可以。 但是,你要是想踩一脚呢,那还是赶紧,马上,快快的闪人。 小心我手里三十米长的大刀。 哼哼。想想都怕 !!!

 

目录(?)[+]

 

一)哈希表简介

非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的次数。

哈希表的特点:关键字在表中位置和它之间存在一种确定的关系。

哈希函数:一般情况下,需要在关键字与它在表中的存储位置之间建立一个函数关系,以f(key)作为关键字为key的记录在表中的位置,通常称这个函数f(key)为哈希函数。

hash : 翻译为“散列”,就是把任意长度的输入,通过散列算法,变成固定长度的输出,该输出就是散列值。

这种转换是一种压缩映射,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。

简单的说就是一种将任意长度的消息压缩到莫伊固定长度的消息摘要的函数。

hash冲突:(大师兄自己写的哦)就是根据key即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经有人先来了。就是说这个地方要挤一挤啦。这就是所谓的hash冲突啦

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

1)开放定址法:

其中 m 为表的长度

对增量di有三种取法:

线性探测再散列   di = 1 , 2 , 3 , ... , m-1

平方探测再散列   di = 1 2 , -12 , 22 , -22 , 32 , -32 , ... , k2 ,  -k2

(大师兄备注:吗单,上面的平方探测再散列是加1的平方;减1的平方,加2的平方,减2的平方,加3的平方,减3的平方。。。加k的平方,减k的平方。卧擦,老师你能再坑点么?法科。要是你直接看这个平方探测再散列的di是怎么来的,不一定能看懂老师ppt的这个写法,是平方的意思。上面的红色字呢,相当于是老师的ppt,是对应上面的图片一起看的。)

随机探测再散列   di 是一组伪随机数列

例子:

我在上面的这个配图底部写的那个红色的12,我当时测试的时候,不知道这个12,也就是上面增量 di 的由来。不知道,限制知道了,那是1的2次方。。。。老师懒得或者说不会给数字打角标。

2)链地址法

上面这个只是老师的ppt,下面放上自己亲自整的测试。

先按照ppt上的hash算法:h(key) = key % 7,算出来对应的hash值,这个hash值暂时就决定,当前的这个值,存放在数组的位置。
都算完之后,就可以,按照这个hash值,依次的,把这些数,都放在下面的数组上。然后就有我自己的这个截图。
和上面的ppt推算的是一致的。

这个做法就是Java的HashMap就是这么实现的,简单的解释下,这个HashMap源码的这个链表产生机制。
在put()方法里面,最后部分有个如下的调用。
addEntry(hash, key, value, i);
解释下几个参数的意思:
1,hash:就是根据key算出来的一个值,源码是这么滴--int hash = hash(key);,
这个算出来的这个就相当于是身份证号码,可以唯一确定一个人一样,唯一确定这个map
2,key:key就是我们在往hashmap里面put键值对的时候的key,使用map的时候,不是可以根据key拿到value吗。
3,value:这个同上啦,就是存的键值对的值。
4,i:源码里面是这么滴--int i = indexFor(hash, table.length);实际意思就是这个键值对存放在底层数组的索引下标。
然后这个i,可以对应到ppt上的那个取模之后的值,也就是确定在数组上的下标。

虽然在put的时候,可能会出现扩容的问题,但是在这咱就不考虑这个,只考虑如何生成链表,以及链表上的键值对的顺序。
createEntry(hash, key, value, bucketIndex);
这个方法就是真正的在创建一个节点到数组上。
这几个参数是一样的,和上面解释的一样的意思。

  1. //先从数组上取下原来的值,给塞到新的节点去,然后把新的节点再放到数组上。
  2. //也就是后来居上的道理。ppt上画的也就有点毛病了。
  3. //老师们嘛,就是 混口饭吃,一般都不斤斤计较这东西的。
  4. void createEntry(int hash, K key, V value, int bucketIndex) {
  5. Entry<K,V> e = table[bucketIndex];
  6. table[bucketIndex] = new Entry<>(hash, key, value, e);
  7. size++;
  8. }
  1. static class Entry<K,V> implements Map.Entry<K,V> {
  2. final K key;
  3. V value;
  4. Entry<K,V> next;
  5. int hash;
  6. /**
  7. * Creates new entry.
  8. */
  9. Entry(int h, K k, V v, Entry<K,V> n) {
  10. value = v;
  11. next = n;
  12. key = k;
  13. hash = h;
  14. }
  15. //******

上面就是hashmap底层数组上存的元素的model。也是能形成链表的关键,有兴趣的可以看看1.7的hashmap的源码。

3、4)再哈希、建立公共溢出区

3.再hash法,就是算hashcode的方法不止一个,一个要是算出来重复啦,再用另一个算法去算。反正很多,直到不重复为止咯。大师兄猜的

4.建立一个公共溢出区域,就是把冲突的都放在另一个地方,不在表里面。具体实现就 不知道啦,也是大师兄猜的。

总结一下的就是下面的四行字:
1.开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
2.再哈希法
3.链地址法(Java hashmap就是这么做的)
4.建立一个公共溢出区

看到这个,自个儿还是得静下心来看看hashmap的源码,1.7的简单易懂,我还做了注解,可以看看,链接如下

Java

佳娃 1.8的 hashmap的理解的连接

Java 1.7 的hashmap 的理解,多了红黑树什么的。

转自:http://blog.csdn.net/qq_27093465/article/details/52269862

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

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

    最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...

  2. Hash(散列函数)简单应用引出解决散列冲突的四种方法

    商店允许顾客通过电话订购商品,并在几天后上门自取.商店的数据库使用客户的电话号码作为其检索的关键字(客户知道自己的电话号码,而且这些电话关键字几乎是唯一的).如何组织商店的数据库,以允许更加高效的进行 ...

  3. Java中取小数点后两位(四种方法)

    摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法)   一 Long是长整型,怎么有小数,是double吧     java.text.D ...

  4. JAVA中获取文件MD5值的四种方法

    JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过Messa ...

  5. Java 判断字符串是否为空的四种方法、优缺点与注意事项

    以下是Java 判断字符串是否为空的四种方法: 方法一: 最多人使用的一个方法, 直观, 方便, 但效率很低: if(s == null ||"".equals(s));方法二: ...

  6. Hash算法解决冲突的四种方法

    Hash算法解决冲突的方法一般有以下几种常用的解决方法 1, 开放定址法: 所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入 公式为 ...

  7. 【数值分析】误差的分析与减少及Matlab解线性方程的四种方法

    1.误差的来源 模型误差:数学模型与实际问题之间的误差 观测误差:测量数据与实际数据的误差 方法误差:数学模型的精确解与数值方法得到的数值解之间的误差:例如 舍入误差:对数据进行四舍五入后产生的误差 ...

  8. 【Java集合学习】HashMap源码之“拉链法”散列冲突的解决

    1.HashMap的概念 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io ...

  9. Python:说说字典和散列表,散列冲突的解决原理

    散列表 Python 用散列表来实现 dict.散列表其实是一个稀疏数组(总是有空白元素的数组称为稀疏数组).在一般书中,散列表里的单元通常叫做表元(bucket).在 dict 的散列表当中,每个键 ...

随机推荐

  1. win 10 提升权限

    问题:每次打开Visual Studio 提示,需要重启以获取管理员权限 解决: 1.Win+R 2.输入:gpedit.msc 3.windows设置->安全设置->本地策略->安 ...

  2. DAY11-MYSQL单表查询

    一 单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二 关键 ...

  3. springmvc 注解式开发 解决中文乱码问题

  4. [poj2976]Dropping tests(01分数规划,转化为二分解决或Dinkelbach算法)

    题意:有n场考试,给出每场答对的题数a和这场一共有几道题b,求去掉k场考试后,公式.的最大值 解题关键:01分数规划,double类型二分的写法(poj崩溃,未提交) 或者r-l<=1e-3(右 ...

  5. 基于IFC的大型三维城市群体——智慧城市模拟

  6. 202. Happy Number 平方循环数

    [抄题]: Write an algorithm to determine if a number is "happy". A happy number is a number d ...

  7. 【转】nginx禁止访问某个文件和目录(文件夹)

    nginx禁止访问所有.开头的隐藏文件设置 location ~* /.* {deny all;} nginx禁止访问目录, 例如:禁止访问path目录 location ^~ /path {deny ...

  8. oracle 监听服务OracleOraDb11g_home1TNSListener打开后立马停止错误

    首先我真得吐槽一下,我安装这个破软件感觉真的是把能遇到的错误都遇到一遍了,生气!!!!!!! 关于监听服务OracleOraDb11g_home1TNSListener打开后立马停止这个错误,我的解决 ...

  9. cakephp增删改查

    增 $this->create(); $ret = $this->save($data); 删 $ret = $this->deleteAll(array('user_id'=> ...

  10. 构建一个在线ASCII视频流服务

    构建一个在线ASCII视频流服务 2018-03-26  正常的文章 1685 什么是ASCII视频流服务? 其实这个名字是咱胡乱起的,具体叫啥我也不清楚,但效果如下: 大家可以在自己的命令行里试下, ...