Python 哈希表的实现与应用

介绍

哈希表一个通过哈希函数来计算数据存储位置的数据结构,通常支持如下操作:

  • insert(key,value):插入键值对(key,value)。
  • get(key): 如果存在键为key的键值对则返回其value,否则返回空值。
  • delete(key): 删除键为key的键值对。

在 Python 当中最具代表的数据结构就是 字典 和 集合,底层所使用的都是哈希表这一数据结构。

直接寻址表

在学习哈希表之前,我们先了解直接寻址表的概念。

假如我们当前定义了一个集合 U,这个集合 U 里面包含了所有的 Key,例如下图:

lvp8i2

我们假设所有可能的数据 Key 的范围为 U,里面包含了0-9这是个数字。然后我们根据这个 U 建立了一个列表,而这个时候我们往2、3、5、8 这四个地方插入了对应的值。具体的数据放在各自的槽当中。

这个时候我们需要查询 5 这个位置的数值,此时我们可以到列表 T 当中直接拿取下标为 5 的元素。其时间复杂度为 O(1)。当然,删除也是很快的,如果要删除 2 这个位置的元素,直接将列表 T 中的内容置为空即可。

优点

因此对于直接寻址表的数据结构来说,我们存放、查找、增加数据的方法都是比较快的。

缺点

  • 如果此时直接寻址表当中存放的是全国人民身份证号的话,则每个人的身份证号都需要一个槽来指定,那么此时这个集合 U 所占用的内存就会变得很大,不符合实际。

  • 而如果集合 U 占用了大量的内存空间,而实际上有数据存放的槽如果只有那么一两个,此时就会导致大量的内存空间遭到浪费。

  • 而如果 key 不是数字,而是一个字符串的话,此时我们就不能通过 key 来查找到对应存放数据的槽了。因此无法处理 key 为非数字的情况。

为了改进 直接寻址表 的缺陷,我们在其基础上加入了哈希函数(具体详见下方内容):

  • 此时我们不再根据 U 的集合内容来规定寻址列表 T 的大小了,而是直接定义一个数值M,假设为 100,此时寻址表里面所能存放数据的槽的数量就为100 个。
  • 我们原来存放数据的方式是获取 U 当中的一个 K,现在我们规定一个函数:h(x),我们通过这个函数来计算此时当前数据存放的位置。

说明:这里 h(x) 是一个函数,用来将原来到域 U 取对应槽位置的过程变成计算得出,将对应的 value 映射到 T 的指定位置当中 。

哈希表

哈希表 (Hash Table,又称为散列表),是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数组成。哈希函数 h(k) 将元素关键字 k 作为自变量,返回元素的存储下标。

假设有一个长度为 7 的哈希表,哈希函数 h ( k ) = k % 7 h(k)=k\%7 h(k)=k%7。元素集合 {14,22,3,5} 的存储方式如下图。

x951FT

注意上面 14 这个元素,如果通过直接寻址表的话, 14 就没法存进去

哈希表解决了直接寻址表占用大量内存的缺陷,但是它自身还是有一定问题的:

哈希表的大小是有限的,而要存储的值的总量是无线的。此时我们想要插入数据 0,根据哈希函数的计算,我们得出结果是 0,而此时 0 这个位置已经被 14 这个元素占用了,因此引出了哈希冲突这个问题。那么该如何解决呢?有以下几种方式:

开放寻址法

开放寻址法:如果哈希函数返回的位置已经有值,则可以向后探测新的位置来存储这个值。

开放寻址法有三种:

  • 线性探测法:如果位置 i 被占用,则探测 i+1,i+2,…
  • 二次探测法:如果位置 i 被占用,则探测 i + 1 2 1^2 12 ,i - 1 2 1^2 12
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值