简单易懂的哈希表介绍

简单易懂的哈希表介绍

1. HashTable哈希表

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

想要知道Hash表相比于其他数据结构的优点,就要先了解其他的数据结构是如何的。

特点数据查找效率数据插入/删除效率
数组使用连续的存储单元根据下标访问O(1)
根据数值查找O(n)
在数组末尾O(1)
在数组中间O(n)且要一个个移动元素
链表每个元素持有下一个元素的引用稳定O(n)不计算寻找插入位置O(1)
二叉树父节点持有左右两个子节点引用如果是有序二叉树
O(logn)
如果是有序二叉树
O(logn)
Hash表根据映射值进行访问不考虑冲突O(1)不考虑冲突O(1)

除了数组能够根据下标访问以外没有其他方法可以做到O(1)访问元素的方法,可以先说的是,Hash表的主体也是一个数组,然后Hash表使用了映射值的方法让它可以像数组一样用O(1)的速度访问数据。

Hash表把每个元素进行提炼,得到一个特征值,用这个特征值作为数组的下标,将元素存入到数组中。而当要访问元素的时候,又根据这个特征值一次性定位到指定的下标来访问元素。也就是说,在Hash表中,这个特征值就代表着元素所在的地址。

而这个将元素提炼得到特征值的过程,就是通过函数来进行的,这个提炼的函数一般就叫做Hash函数,然后这个特征值就叫Hash值。

举例:开辟一个长度为16的数组array,连续存入多个整数,其中Hash函数f(x) = x % 16。

  1. 存入数字17,f(17) = 1,将17存入到array[1]中。
  2. 存入数字34,f(34) = 2,将34存入到array[2]中。
  3. 想要知道35是否在数组中,f(35) = 3,访问array[3]发现为空,得到不在数组中的答案。

Hash表截图1
这个例子可以明显的看出两个问题:

  1. 如果我现在想要存入数字1或者数字33,但是Array[1]已经被17占领了,那岂不是存不进去或者17就被覆盖了?
  2. 如果我现在想查数字1或者数字33是否在数组内,无法根据Array[1]中已经有数字来判断是否真的存在。

这两个问题实际上是同一个问题:如果多个不同的对象根据Hash函数计算得到的Hash值相同,要如何处理。
这种情况我们称作为哈希冲突或者哈希碰撞。哈希冲突无法避免,因为Hash函数只能做到逻辑上的唯一性,无法做到物理上的唯一性。一般在遇到这种情况的时候,有以下四种预选方案:

  • 开放寻址法:当遇到冲突的时候,将这个元素放在数组的下一个位置上。
  • 再散列法:准备多个散列函数,当第一个散列函数冲突后,再使用第二散列函数再次定位数组下标。
  • 链地址法:每个元素不仅仅是元素,也是一个链表,当遇到冲突时,就把元素加入到链表的末尾。
  • 建立公共溢出区:在创建数组的时候,专门划分一块区域来存放冲突后的元素,当遇到冲突后就遍历这一块区域来进行查找。

由于平时Java用的的HashMap是用链地址法来处理,我就以这个方法来详细说明:存入数组中的每个元素都是一个链表,拥有一个同类型的next引用,平时它们指向null,如果遇到冲突的时候,就将新加入的冲突元素加入到链表中;而在访问的时候,在找到下标的同时,也会遍历整个链表来查找。

和上面的例子继续往下举例

  1. 存入数字1,f(1) = 1,由于Array[1]上已经有17,将1存入到17的后面,此时Array[1]的内容是 17 -> 1。
  2. 存入数字33,f(33) = 1,由于Array[1]上已经有17,将33存入到链表后面,此时Array[1]是 17 -> 1 -> 33。
  3. 查找数字49是否在数组内,f(49) = 1,遍历Array[1]的链表 17 -> 1 -> 33发现没有49,得到不在数组的答案。

在这里插入图片描述
这个时候可以发现,当存入数据的时候,一旦求出特征值,就直接加在链表后面,这不就是链表存入数据的O(1)复杂度吗。

Hash就是结合了数组和链表两者的优势,达到了访问时使用数组的特性达到O(1)复杂度,存储时使用链表的特性达到O(1)复杂度,是一个集合两家之长的数据结构,实现了访问简单,插入删除数据也简单的操作。

参考材料

Java集合之一—HashMap - 深入浅出学JAVA - 优快云博客
https://blog.youkuaiyun.com/woshimaxiao1/article/details/83661464
数据结构 Hash表(哈希表) - 积跬步 至千里 - 优快云博客
https://blog.youkuaiyun.com/u011109881/article/details/80379505
哈希表_百度百科
https://baike.baidu.com/item/%E5%93%88%E5%B8%8C%E8%A1%A8/5981869?fromtitle=Hash%E8%A1%A8&fromid=8485677&fr=aladdin
(1)美团面试题:Hashmap的结构,1.7和1.8有哪些区别,史上最深入的分析 - 王伟的博客 - 优快云博客
https://blog.youkuaiyun.com/qq_36520235/article/details/82417949

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值