算法入门——散列表

目录

散列表

散列函数

散列表的内部机制

冲突

性能

填装因子

散列表的应用案例

小结


散列表

散列表:顾名思义也就是离散的或者零散,即不连贯的列表,也可以类比于离散数组。

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

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

散列表就是一个即查即得得一个表,python中的字典就是散列表,你输入键,他会很快返回一个值,时间复杂度基本为O(1),相比较列表和链表,运行速度快许多。

散列函数

就是一种映射关系的函数,就是无论你给它什么数据,它都还你一个数字,就是散列函数“将输入映射到数字”。

它也需要满足一些要求:

  • 它必须是一致的。就是你输入同一个key时,f(key)得到的值都必须相同。
  • 它应将不同的输入映射到不同的数字。就是尽量不同的key,对应着不同的f(key)值,这样才是一个好的散列函数。

散列函数总是将同样的输入映射到相同的索引,不同的输入映射到不同的索引,同时它知道数组长度,只返回有效的索引。这样散列函数每次都能准确找到输入对应的值。

我们就可以通过散列函数和数组构建出散列表这种数据结构,但是这不需要我们去实现,现在每一门语言都已经提供了散列表的实现,比如python中的字典。

良好的散列函数让数组中的值呈均匀分布。

糟糕的散列函数让值扎堆,导致大量冲突。

散列表的内部机制

冲突

就是给两个键分配的位置相同,即两个键映射到了同一个位置。

这时候的解决方法可以在这个位置存储一个链表(但建议不这样做),链表短的话,对整体性能没啥影响,但是链表一长,此时的散列表就会变得很慢,最好还是将这些键均匀的分布在散列表中,避免分配到同一个位置。

性能

在平均情况下(最优情况),散列表执行各种操作的时间都为O(1)。O(1)为常量时间,不代表马上,而是说无论散列表多大,运行的时间都相同。

平均情况最糟情况数组链表
查找O(1)O(n)O(1)O(n)
插入O(1)O(n)O(n)O(1)
删除O(1)O(n)O(n)O(1)

平均情况下,散列表运行的挺快,但是在出现前面所说的冲突时,它就会运行很慢,就很有可能达到这种最糟的情况。

因此我们需要避免冲突,即

  • 较低的填装因子
  • 良好的散列函数

填装因子

这个散列表的填装因子为3/5,但是当填装因子大于1意味着此时散列表包含的元素超过了数组的位置数,此时你就需要在散列表中添加位置,这样被称为调整长度(resizing)。

一般而言,当填装因子大于0.7时,就调整散列表的长度,通常是将数组长度扩大一倍。

散列表的应用案例

  • 将散列表用于查询
  • 防止重复,比如投票一人一票制
  • 将散列表用作缓存,如web服务器,为了避免通过再次处理生成它们

小结

  • 散列表是一种功能很强大的数据结构,操作速度快
  • 我们不用自己去实现散列表,几乎所有的编程语言都提供了它的实现
  • 你可以结合散列函数和数组来创建散列表
  • 冲突很糟糕,尽量避免冲突
  • 散列表的查找,插入和删除速度都非常快
  • 散列表适合用于模拟映射关系
  • 一旦填装因子超过0.7,就该调整散列表的长度
  • 散列表可用于缓存数据(如在web服务器上)
  • 散列表非常适合用于防止重复

注:内容来源于《算法图解》和百度百科

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值