数据结构---散列表

本文介绍了哈希表的基本概念,包括哈希函数的作用、如何通过哈希函数将键值映射到数组下标,以及解决哈希冲突的方法。同时探讨了哈希表的读写操作,并解释了在哈希表达到一定饱和度时如何进行扩容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


散列表也叫作 哈希表(hash table),这种数据结构提供了键(Key)和值
(Value)的映射关系。只要给出一个Key,就可以高效查找到它所匹配的Value,时间复杂度接近于O(1)。

在这里插入图片描述

哈希函数

散列表在本质上也是一个数组。
存在的问题是:数组只能根据下标,像a[0]、a[1]、a[2]、a[3]、a[4]这样来访问,而散列表的Key则是以字符串类型为主的。

解决方法:我们需要一个“中转站”,通过某种方式,把Key和数组下标进行转换。这个中转站就叫作哈希函数。

在这里插入图片描述
在JAVA中,每一个对象都有属于自己的hashcode,这个hashcode是区分不同对象的重要标识。无论对象自身的类型是什么,它们的hashcode都是一个整型变量。
将hashcode转换为数组下标index公式:

index = HashCode (Key) % Array.length

通过哈希函数,我们可以把字符串或其他类型的Key,转化成数组的下标index。

散列表读写

写操作就是在散列表中插入新的键值对(在JDK中叫作Entry)。
调用hashMap.put(“002931”, “王五”),意思是插入一组Key为002931、Value为王五的键值对。
第1步,通过哈希函数,把Key转化成数组下标5。
第2步,如果数组下标5对应的位置没有元素,就把这个Entry填充到数组下标5
哈希冲突
在这里插入图片描述
由于数组的长度是有限的,当插入的Entry越来越多时,不同的Key通过
哈希函数获得的下标有可能是相同的。例如002936这个Key对应的数组下标是2;
002947这个Key对应的数组下标也是2。

解决办法:开放寻址法、链表法
开放寻址法:Entry6通过哈希函数得到下标2,该下标在数组中已经有了其他元素,那么就向后移动1位,看看数组下标3的位置是否有空。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
链表法:HashMap数组的每一个元素不仅是一个Entry对象,还是一个链表的头节点。每
一个Entry对象通过next指针指向它的下一个Entry节点。当新来的Entry映射到与
之冲突的数组位置时,只需要插入到对应的链表中即可。 (数组+链表)
JAVA用这种方法解决哈希冲突

在这里插入图片描述

读操作就是通过给定的Key,在散列表中查找对应的Value。
步骤:
第1步,通过哈希函数,把Key转化成数组下标2。
第2步,找到数组下标2所对应的元素,如果这个元素的Key是002936,那么就找到了;如果这个Key不是002936也没关系,由于数组的每个元素都与一个链表对应,我们可以顺着链表慢慢往下找,看看能否找到与Key相匹配的节点。
在这里插入图片描述

扩容

什么情况需要扩容
当经过多次元素插入,散列表达到一定饱和度时,Key映射位置发生冲突的概率会逐渐提高。这样一来,大量元素拥挤在相同的数组下标位置,形成很长的链表,对后续插入操作和查询操作的性能都有很大影响。(散列表是基于数组实现的,那么散列表也要涉及扩容的问题。)

在这里插入图片描述
扩容条件:

HashMap.Size >= Capacity×LoadFactor

其中
Capacity,即HashMap的当前长度
LoadFactor,即HashMap的负载因子,默认值为0.75f

扩容步骤:

  1. 扩容,创建一个新的Entry空数组,长度是原数组的2倍。
  2. 重新Hash,遍历原Entry数组,把所有的Entry重新Hash到新数组中。为什么要重新Hash呢?因为长度扩大以后,Hash的规则也随之改变。
    在这里插入图片描述
    扩容后
    在这里插入图片描述
    注意:当多个Entry被Hash到同一个数组下标位置时,为了提升插入和查找的效率,HashMap会把Entry的链表转化为红黑树这种数据结构。

总结

散列表也叫哈希表,是存储Key-Value映射的集合。对于某一个Key,散列表可以在接近O(1)的时间内进行读写操作。散列表通过哈希函数实现Key和数组下标的转换,通过开放寻址法和链表法来解决哈希冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值