Python 哈希表的实现——字典

接触过 Python 的小伙伴应该对【字典】这一数据类型都了解吧

虽然 Python 没有显式名称为“哈希表”的内置数据结构,但是字典是哈希表实现的数据结构

在 Python 中,字典的键(key)被哈希,哈希值决定了键对应的值(value)在字典底层数据存储中的位置

那么今天我们就来看看哈希表的原理以及如何实现一个简易版的 Python 哈希表

ps:文中提到的 Python 指的是 CPyhton 实现

何为哈希表?

哈希表(hash table)通常是基于“键-值对”存储数据的数据结构

哈希表的键(key)通过哈希函数转换为哈希值(hash value),这个哈希值决定了数据在数组中的位置。这种设计使得数据检索变得非常快

举个例子,下面有一组键值对数据,其中歌手姓名是 key,歌名是 value

+------------------------------+
|   Key        |   Value       |
+------------------------------+
| Kanye        | Come to life  |
| XXXtentacion | Moonlight     |
| J.cole       | All My Life   |
| Lil wanye    | Mona Lisa     |
| Juice WRLD   | Come & Go     |
+------------------------------+

如果我们想要将这些键值对存储在哈希表中,首先需要将键的值转换成哈希表的数组的索引,这时候就需要用到哈希函数了

哈希函数是哈希表实现的主要关键,它能够处理键然后返回存放数据的哈希表中对应的索引

一个好的哈希函数能够在数组中均匀地分布键,尽量避免哈希冲突(两个键返回了相同的索引)

image-20231124102113576.png

哈希函数是如何处理键的,这里我们创建一个简易的哈希函数来模拟一下(实际上哈希函数要比这复杂得多)

def simple_hash(key, size):
    return ord(key[0]) % size

这个简易版哈希函数将歌手名(即 key)首字母的 ASCII 值与哈希表大小取余,得出来的值就是歌名(value)在哈希表中的索引

那这个简易版哈希函数有什么问题呢?聪明的你一眼就看出来了:容易出现碰撞。因为不同的键的首字母有可能是一样的,就意味着返回的索引也是一样的

例如我们假设哈希表的大小为 10 ,我们以上面的歌手名作为键然后执行 simple_hash(key, 10) 得到索引

image-20231124111316696.png

可以看到,由于Juice WRLDJ.cole 的首字母都一样,哈希函数返回了相同的索引,这里就发生了哈希碰撞

虽然几乎不可能完全避免任何大量数据的碰撞,但一个好的哈希函数加上一个适当大小的哈希表将减少碰撞的机会

当出现哈希碰撞时,可以使用不同的方法(例如开放寻址法)来解决碰撞

应该设计健壮的哈希函数来尽量避免哈希碰撞

我们再来看其他的键,Kanye 通过 simple_hash() 函数返回 index 5,这意味着我们可以在索引 5 (哈希表的第六个元素)上找到 其键 Kanye 和值Come to life

image-20231124140016486.png

哈希表优点

在哈希表中,是根据哈希值(即索引)来寻找数据,所以可以快速定位到数据在哈希表中的位置,使得检索、插入和删除操作具有常数时间复杂度 O(1) 的性能

与其他数据结构相比,哈希表因其效率而脱颖而出

不但如此,哈希表可以存储不同类型的键值对,还可以动态调整自身大小

Python 中的哈希表实现

在 Python 中有一个内置的数据结构,它实现了哈希表的功能,称为字典

Python 字典(dictionary,dict)是一种无序的、可变的集合(collections),它的元素以 “键值对(key-value)”的形式存储

字典中的 key 是唯一且不可变的,这意味着它们一旦设置就无法更改

my_dict = {"Kanye": "Come to life", "XXXtentacion": "Moonlight", "J.cole": "All My Life"}

在底层,Python 的字典以哈希表的形式运行,当我们创建字典并添加键值对时,Python 会将哈希函数作用于键,从而生成哈希值,接着哈希值决定对应的值将存储

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值