简单易懂的哈希表介绍
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。
- 存入数字17,f(17) = 1,将17存入到array[1]中。
- 存入数字34,f(34) = 2,将34存入到array[2]中。
- 想要知道35是否在数组中,f(35) = 3,访问array[3]发现为空,得到不在数组中的答案。
这个例子可以明显的看出两个问题:
- 如果我现在想要存入数字1或者数字33,但是Array[1]已经被17占领了,那岂不是存不进去或者17就被覆盖了?
- 如果我现在想查数字1或者数字33是否在数组内,无法根据Array[1]中已经有数字来判断是否真的存在。
这两个问题实际上是同一个问题:如果多个不同的对象根据Hash函数计算得到的Hash值相同,要如何处理。
这种情况我们称作为哈希冲突或者哈希碰撞。哈希冲突无法避免,因为Hash函数只能做到逻辑上的唯一性,无法做到物理上的唯一性。一般在遇到这种情况的时候,有以下四种预选方案:
- 开放寻址法:当遇到冲突的时候,将这个元素放在数组的下一个位置上。
- 再散列法:准备多个散列函数,当第一个散列函数冲突后,再使用第二散列函数再次定位数组下标。
- 链地址法:每个元素不仅仅是元素,也是一个链表,当遇到冲突时,就把元素加入到链表的末尾。
- 建立公共溢出区:在创建数组的时候,专门划分一块区域来存放冲突后的元素,当遇到冲突后就遍历这一块区域来进行查找。
由于平时Java用的的HashMap是用链地址法来处理,我就以这个方法来详细说明:存入数组中的每个元素都是一个链表,拥有一个同类型的next引用,平时它们指向null,如果遇到冲突的时候,就将新加入的冲突元素加入到链表中;而在访问的时候,在找到下标的同时,也会遍历整个链表来查找。
和上面的例子继续往下举例:
- 存入数字1,f(1) = 1,由于Array[1]上已经有17,将1存入到17的后面,此时Array[1]的内容是 17 -> 1。
- 存入数字33,f(33) = 1,由于Array[1]上已经有17,将33存入到链表后面,此时Array[1]是 17 -> 1 -> 33。
- 查找数字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