[哈希表基础知识]

什么是哈希表

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

官方的解释可能有点懵,直白来讲其实数组就是一张哈希表。

哈希作为一个非常常用的查找数据结构,它能够在O(1) 的时间复杂度下进行数据查找。
比方说我有一个集合有如下数据,而我想要快速查找一个数据在不在这个集合中,我应该采取什么办法?
哈希表
一般情况下可以使用遍历的方式,但是如果数据量太多,则每次遍历的代价将不可接受。

那么,如果它们是有序的,则可以使用树形数据结构进行二分查找,效率也是非常的高,但很不巧我们这些数据是无序的。

所以就有人想到一个很巧妙的办法来寻找它,就是将要寻找的数据(下文称为键)进行一次计算得到一个数组下标值,然后将这个值放到对应的数组里。
哈希表
以后我们每次寻找的时候都对键进行计算从而得到一个数组下标值,然后通过下标拿到数组对应的数据,就能知道它是否存在于这个数组中了。

这种数据查找的数据结构就叫做哈希表,对键的计算的方法叫做哈希函数。

什么是哈希函数

哈希函数可以把给定的数据转换成固定长度的无规律数值。转换后的无规律数值可以作为数据摘要应用于各种各样的场景。

我们可以把哈希函数想象成搅拌机,如下图所示。
在这里插入图片描述
将数据放入搅拌机里
在这里插入图片描述
经过哈希函数计算后,搅拌机会输出固定长度的无规律数值。输出的无规律数值就是“哈希值”。哈希值虽然是数字,但多用十六进制来表示。
在这里插入图片描述
计算机使用二进制管理所有数据,虽然哈希值是用十六进制表示的,但它也是数据,计算机在存储哈希值时,会通过计算将其转换为二进制进行管理。
在这里插入图片描述

哈希函数的特征

  1. 哈希值的长度与输入数据的大小的无关
  2. 输入相同的数据,输出的哈希值也必定相同
  3. 输入相似的数据,输出的哈希值必定不同
  4. 输入的数据完全不同,但输出的哈希值可能是相同的。这种情况被称作“哈希冲突”
  5. 哈希值是不可逆的,通过哈希值不可能反向推算出原本的数据。

哈希冲突

哈希冲突是指多个不同的键散列到了同一个数组下标位置上,案例如下:
在这里插入图片描述
在上图中, 这三个字经过散列之后的数组下标都是0,而且因为是三个不同的值,所以也不能直接在数组上覆盖,那么我们就需要有一个办法把这三个值存起来。

一般哈希冲突有两种解决方法, 拉链法和开放地址法。

拉链法:就是在冲突的下标元素处维护一个链表,所有冲突的元素都依次放到这个链表上去:
在这里插入图片描述
在上图中,将冲突的两个键就按照顺序放在了链表中,下次寻找时只需要查看该数组元素以及遍历这个链表即可。
其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。

开放地址法:是一种比较简单的解决冲突的方法,它的原理非常简单:
在这里插入图片描述
就是在第一个字已经占用了下标0之后,第二个字则向后进行寻找空余的下标,找到之后将自己设置进去,所以字在下标1处,而字在下标2处。

根据寻找下标的方式不同,开放地址法可以分为以下几种:
在这里插入图片描述

其实原理都差不多,都是在当前下标的基础上向后寻找空余的下标,不过步长不一样罢了。

常见的三种哈希结构

  1. 数组(array)
  2. 集合(set)
  3. 映射(map)
    在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:
    set底层实现原理
    map底层实现原理

哈希表的缺点

1.哈希冲突太多会导致部分查找线性。
2.不能进行范围查找。

对于第一个缺点,一般正常使用是不会出现太多冲突

对于第二个缺点,这是哈希表一个无法回避的硬伤,在需要范围的查找的需求下,还是树类数据结构更能兼顾范围查找与指数级速度。

当然哈希表在记录数据量很大的时候,处理记录的数据很快,平均操作时间是一个不太大的常数。这足以掩盖很多缺点。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-Gaojs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值