哈希表是我们经常频繁使用的数据结构,所以它的知识点比较重要,如HashMap啊,就是哈希表结构,哈希表的底层是数组+链表结构的,非常之聪明,两者优点结合,数组查询快,链表增删快,并且hash采用算法分析定位地址,而不用再像数组一样需要遍历。

哈希表为什么采用数组+链表的结构呢?

答:通过一定算法计算出来的数字就可以对应数组下标找到对应位置,假如现在计算完的数字是0需要定位到0坐标上,然后又有一个数据需要存储,计算完之后位置还是0,那现在怎么办呢,那也不能覆盖把,这种问题的出现也叫哈希碰撞,那现在解决办法就是加链表,当发现计算完的位置是一样的就存储在一连串的链表里就能实现。

我就不瞎巴巴了,还是上官方介绍哈希表的介绍把

1.哈希表的介绍

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

 

哈希表可以提供快速的插入和查找工作,哈希表运算的非常快,而且编程实现也比较容易。哈希表是数组和链表结构

记录的存储位置=f(关键字),这里的对应关系f称为散列函数,又称为哈希(哈希函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表

Java数据结构-哈希表讲解(Hash)

--视频资料介绍图片

Java数据结构-哈希表讲解(Hash)

2.哈希冲突

由于存储空间有限,hash计算以后可能不同的关键字映射到同一个哈希地址上,这种现象称之为哈希冲突,比如h(16)=16%11=5,h(27)=27%11=5,两个哈希地址就冲突了

Java数据结构-哈希表讲解(Hash)

--视频资料介绍图片

Java数据结构-哈希表讲解(Hash)

hash冲突是不可避免的,要解决hash冲突需要以下几种方式

3.开放地址法

3.1 线性探查(Linear Probing)

哈希冲突解决策略:开放寻址法(将所有的元素都存放在哈希表内的数组中,不使用额外的数据结构)

开放寻址法最简单的一种实现就是线性探查,步骤如下:

  1. 当插入新的元素时,使用哈希函数在hash表中定位元素位置;
  2. 检查哈希表中该位置是否已经存在元素,如果该位置为空,则插入并返回,否则转向步骤3
  3. 如果该位置为i,则检查i+1是否为空,如果已被占用,则检查i+2,以此类推,直到找到一个内容为空的位置。

Java数据结构-哈希表讲解(Hash)

视频资料图

Java数据结构-哈希表讲解(Hash)

线性探查(Linear Probing)方式虽然简单,但并不是解决冲突的最好的策略,因为会导致同类hash的聚集,这导致搜索hash表时冲突依然存在,例如上图例子中的哈希表,如果我们要访问Edward的信息,因为Edward的社保号是111-00-1235 哈希为1235,然而我们在1235找到的位置是Bob,所以再搜索1236,找到的确是Danny,以此类推才能找到最终答案,所以在查找的时候也会出现冲突的。

开放地址法的线性探测缺点就是,数据项聚集,越来越大,越到后面找到的空位插入数据项需要时间越多。

你已经猜到了,一个知识点第一个讲到的总是有缺陷,需要弥补的,那么二次探查和二度哈希出现在江湖。

3.2 二次探查(Quadratic Probing)

一种改进的方式为二次探查(Quadratic Probing),即每次检查位置空间的步长为平方倍数,也就是说,如果位置s被占用,则首先检查s+1的平方,然后检查s-1的平方,s+2的平方,s-2的平方,依次类推而不是像线性探查那样s+1,s+2.....方式增长,尽管如此,二次探查同样也会导致同类哈希聚集问题。

3.3 二度哈希(Rehashing)/双重哈希(Double Hashing)

啊呀呀,看hashmap看的脑瓜子疼啊,下次在梳理二度哈希链地址法等等

 

 

相关文章:

  • 2022-01-22
  • 2021-07-12
  • 2021-04-16
  • 2022-12-23
  • 2021-12-26
  • 2021-06-14
  • 2021-10-09
猜你喜欢
  • 2021-07-21
  • 2021-10-20
  • 2021-12-25
  • 2021-09-03
相关资源
相似解决方案