python基础之字典与集合实现原理

更多精彩内容,欢迎关注微信公众号:tmac_lover

上一篇介绍python中字典和集中时,提到,字典和集合的优势在于增删改查非常高效,而高效的原因就在于,python中字典和集合这两个数据结构是基于散列表来实现的。散列表也叫哈希表,英文是hashtable。是一种非常高效的基础数据结构,今天我们介绍一下散列表的原理,了解了原理之后,就会很容易理解为什么字典和集合的增删改查如此高效。

什么是散列表

散列表听上去好像很玄乎,但是实际上在我们的生活中却非常的常见。举个很简单的例子,我们读大学的时候,辅导员老师那里的excel表里有每个学生的信息,如果我们想要查找某一个学生的信息,使用什么方法最迅速呢?
一种很容易想到的方法是打开excel,然后从第一行开始一行一行的看,直接看到我们想要找的那个学生的那一行为止,可想而知,如果有5000个学生,很不巧这名学生刚好在excel表的最后一行,是不是要耗很长时间才能找到。这种方法有点类似于列表,查找的时间复杂度为O(n)。
还有另外的方法,因为每个学生都有学号,并且学号是连续的,如果我们存储的时候,直接按学号从小到大的顺序,从第一行开始存,查找的时候,只要知道学生的身份证号,是不是就能很快速的定位到该名学生在excel表格里的第几行,然后就可以直接拿到学生的信息。使用这种方式,只需要经过一次计算,就能确定学生信息的位置,而这个计算的时间是相对固定的。这就是典型的一种散列表的思想,它查找的时间复杂度是O(1)。这个计算偏移的方法,就相当于散列函数。这里学生的学号就是散列表中的键(key)。
用图表示就像下面这样:

hash table

我们只需要设计一个散列函数,然后利用这个散列函数,根据学生的学号就可以计算出每个学生信息在excel表里的存储位置。这样就可以实现快速的增删改查,效率非常的高。

以上就是散列表所包含的非常基础的思想。当然实际的散列表的实现,还要考虑的因素有很多,比如:

  • hash函数的设计,这个函数要求对同样的输入,输出一定要相同,而对于不同的输入,输出尽量减少冲突
  • 如果出现散列冲突(即两个Key经过散列函数之后输出相同),使用什么方式解决散列冲突
  • 装载因子的设置,因为散列表是可以增加元素的,为了避免空间满时减加元素时元素搬移太耗时,需要为散列表预留一些空间,当表中元素达到某个域值时,对整个散列表进行整体搬移和扩容,这个域值就是装载因子

如果想更深入的了解散列表,可以自行查阅一些资料,在这里,我们只需要了解散列表的实现原理,以及为什么散列表的增删改查效率如此之高就可以了。

为什么字典和集合是无序的

了解了上面所说的散列表的基本原理之后,我们知道,散列表中元素的实际存储位置是由所设计的散列函数对键(key)进行运算后得出的。上面所举的学号的例子比较特殊,使用的散列函数相当于只是对学号数字取了一个偏移来得到学生信息存储位置。而实际上大多数的散列函数在对键进行计算后,得到的存储位置是随机的,并不连续,所以元素的存储位置也就不一定和输入的顺序相同。

列表可以做为键(key)吗

讨论这个问题前,我们需要知道字典的键必须要求是可以散列的,而一个可散列的对象必须满足以下要求:

  • 支持hash()函数,并且通过hash()方法所得到的散列值是不变的
  • 支持通过eq()方法检测相等性
  • 若a==b为真,则hash(a) == hask(b)也必须为真

通过下面代码测试一下:

1l = [1,2,3,4]
2print(hash(l))

运行会报如下错误:

1Traceback (most recent call last):
2  File "<stdin>", line 1, in <module>
3TypeError: unhashable type: 'list'

实际上,list并没有实现hash()这个魔法函数,因为只有不可变对象,才可以进行hash, 像字符串,字典这种都属于不可变对象,而集合,列表,字典都属于可变对象,所以它们无法作为字典的key。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值