什么是哈希表?

哈希表也叫散列表,它是基于数组的。这间接带来了一个优点:查找的时间复杂度为 O(1)、当然,它的插入时间复杂度也是 O(1)。还有一个缺点:数组创建后扩容成本较高。
哈希表中有一个“主流”思想:转换。一个重要的概念是将「键」或「关键字」转换成数组下标。这由“哈希函数”完成。

什么是哈希函数?

由上,其作用就是将非 int 的键/关键字转化为 int 的值,使可以用来做数组下标。
比如,HashMap 中就这样实现了哈希函数:

static final int hash(Object key){int h;return (key==null)?0:(h=key.hashCode())^(h>>>16);   // 通过异或提高hash的“散列度”,降低冲突
}

其中利用了 hashCode 完成转换。虽然哈希函数有很多种实现,但都应当满足这三点:

  • 计算得到的是非负整数;
  • 如果 key1==key2,则 hash(key1)==hash(key2)
  • 如果 key1!=key2,则 hash(key1)!=hash(key2)
  1. 并不是所有的键/关键字都需要被转换才能做下标(索引)
  2. 就像 JS 中也有类似的、但仅用于检测键是否能用来做数组下标的方法:JavaScript数组索引检测中的数据类型问题

什么是哈希冲突?

上面提到了 hashMap —— 一个java中提供的数据集。我们先来了解下:首先,hashMap 本质上是一个容器,它为了达到快速索引的目的,使用了数组结构“快速定位”的特性。
hashMap 中为了更快找到插入的值,建立了插入值和数组下标的关系:pos(下标)=key(值)%size(数组大小)

比如:数组长度为10

  1. 插入100,有100%10=0;
  2. 插入201,有201%10=1;
  3. 插入403,有403%10=3;

但是如果这样设计的话,我现在再插入200,会怎么样?
这就是数组的一个缺点:插入特殊值比较“费劲”。不如我们干脆将数组涉及成这样:

引入链表特性,一个节点就包括一个值和一个next指针。

现在再插入上面那些值,就变成了这样:

这时候如果再插入值300,怎么做?

类似这样(当两个或以上的key的pos相同,且key不同)其实就是我们提到的“hash冲突”,而 hashMap 中解决hash冲突的方法就是上面说的“单链表”!
但是这又有一个问题:虽然用有序链表的方式可以减少不成功的查找时间(因为只要有一项比查找值大,就说明没有我们需要查找的值),但是不能加快成功的查找。如果冲突的链表太长,则链表查找时需要从“头”遍历的劣势就暴露出来了 —— 针对这个问题,JDK1.8后用 红黑树 做了优化!

但是我们先撇开红黑树,用单链表的形式说明一下哈希表的操作:

/*** 链表基类:链表法解决哈希冲突用的是有序链表!
*/
public class SortedLinkList {private Link first;public SortedLinkList(){first = null;}/*** 链表插入* @param link*/public void insert(Link link){int key = link.getKey();Link previous = null;Link current = first;while (current!=null && key >current.getKey()){previous = current;current = current.next;}if (previous == null)first = link;elseprevious.next = link;link.next = current;}/*** 链表删除* @param key*/public void delete(int key){Link previous = null;Link current = first;while (current !=null && key !=current.getKey()){previous = current;current = current.next;}if (previous == null)first = first.next;elseprevious.next = current.next;}/*** 链表查找* @param key* @return*/public Link find(int key){Link current = first;while (current !=null && current.getKey() <=key){if (current.getKey() == key){return current;}current = current.next;}return null;}
}

链表法哈希表插入:

public void insert(int data) {Link link = new Link(data);int key = link.getKey();int hashVal = hash(key);array[hashVal].insert(link);
}

链表法哈希表查找:

public Link find(int key) {int hashVal = hash(key);return array[hashVal].find(key);
}

链表法哈希表删除:

public void delete(int key) {int hashVal = hash(key);array[hashVal].delete(key);
}

除了链表法,解决哈希冲突还有一个方法:开放寻址法。
在开放地址法中,若数据不能直接存放在哈希函数计算出来的数组下标时,就需要寻找其他位置来存放。在开放地址法中有三种方式来寻找其他的位置,分别是

  • 线性探测
  • 二次探测
  • 再哈希法

三问了解哈希表和哈希冲突相关推荐

  1. python 哈希表_哈希表哪家强?编程语言找你来帮忙!

    点击关注上方"五分钟学算法", 设为"置顶或星标",第一时间送达干货. 转自编程技术宇宙 哈希表华山论剑 比特宇宙编程语言联合委员会准备举办一次大会,主题为哈希 ...

  2. 哈希表及哈希冲突解决办法

    哈希表及哈希冲突解决办法 目录 什么是哈希表? 哈希表的数据结构 哈希冲突 哈希冲突解决办法 1. 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直 ...

  3. 除留余数法构造哈希表_哈希表算法原理

    基本概念 哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构.通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数. 哈 ...

  4. ds哈希查找—二次探测再散列_大白话之哈希表和哈希算法

    哈希表概念 哈希表(散列表),是基于关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数(哈希函数 ...

  5. 大白话之哈希表和哈希算法

    哈希表概念 哈希表(散列表),是基于关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数(哈希函数 ...

  6. 哈希表构造与处理冲突方法

    我们知道:哈希表是一个固定大小的数组,数组的每个元素是一个链表(单向或双向)的头指针.如果Key一样,则在一起,如果Key不一样,则不在一起.哈希表的查询是飞快的.因为它不需要从头搜索,它利用Key的 ...

  7. LeetCode哈希表(哈希集合,哈希映射)

    文章目录 哈希表 1.原理 2.复杂度分析 题目&推荐列表 哈希集合的应用 0.常用解题模板 1.lc217 存在重复元素 2.lc136 只出现一次的数字 3.快乐数 哈希映射的应用 0.常 ...

  8. 哈希表(哈希函数和处理哈希冲突)_20230528

    哈希表(哈希函数和处理哈希冲突) 前言 关于哈希表的主题的小记原计划5月23日完成,由于本人新冠阳性,身体发烧乏力,周末感觉身体状况稍加恢复,赶紧打开电脑把本文完成,特别秉承"写是为了更好地 ...

  9. [算法入门笔记] 9. 哈希表与哈希函数

    文章目录 1. 哈希表与哈希函数的实现 2. 设计RandomPool结构 3. bitmap 3.1 概述 3.2 常用操作 3.2.1 存储数据 3.2.2 添加操作 3.2.3 删除操作 3.2 ...

最新文章

  1. Linux文件系统:概览(思维导图)
  2. asp.net获取网站路径
  3. oracle rowid mysql_相当于Oracle的RowID在MySQL中
  4. Web Dynpro Controller
  5. 判断是否在数组中,若在输入其下标,否则输入-1
  6. MySQL笔记-事务理论及并发存在的三个问题(脏读、不可重复读、幻读)演示
  7. java中random方法取值范围_Java中的Random()函数
  8. 在Linux上安装JDK9
  9. iptables: Resource temporarily unavailable.问题
  10. asp木马伪装成图片或其它,上传漏洞终极解决方法
  11. PHP跨域获取session
  12. 深度学习花书+机器学习西瓜书电子版我找到了
  13. 构建系统发育树~序列对比 MEGA、MAFFT(图文教程)
  14. 『天涯杂谈』十大古今名人语录经典(2007版)
  15. Redis trouble21 -- aof持久化导致redis命令阻塞
  16. html动态背景分享,酷炫一款动态背景(HTML +js canvas)
  17. 七夕超多表情包入侵 - 100%提升博客美感(六千粉丝福利)!
  18. Hive权限管理,增加用户,授权
  19. 怎么在Ubuntu手机上发送短信及拨打电话
  20. 通达信 服务器 修改,通达信验证服务器数据库修改

热门文章

  1. 别让企业发展成为悲剧
  2. MPAndroidChart—— pieChart 属性详解
  3. verilog牛客网刷题代码汇总
  4. QT 调用vs写的dll 使用OutputDebugString输出调试信息
  5. Silver Cow Party (最短路)
  6. web-前端设计之鼠标悬停样式
  7. arcgis python二次开发_arcgis二次开发python_arcgis二次开发是什么_arcgis二次开发
  8. 不服不行!终于有人把AMS和WMS讲明白了!
  9. 命令提示符(cmd)中的tracert命令详解
  10. JAVA小程序简单学籍系统参考代码,登陆小程序,Jtree //Jtree,JDBC,Jframe