Python字典集合数据结构深入理解
来源:互联网 发布:高晓松酒驾 知乎 编辑:程序博客网 时间:2024/06/05 14:51
说明
在python中字dict和set是非常常用的两种数据结构,但是两种数据结构为什么要放在一起讨论。因为他们之所以拥有非常快的速度,是因为他们的内部结构都是散列表(散列表其实是一个稀疏数组总是有空白元素的数组称为稀疏数组)
dict中的散列表
- 散列表算法
正常想要获取dict中的值,首先要知道key通过dict[key]获取对应的value,在散列表中为了达到这种操作,首先会计算key的hash值即散列值,把这个值最低的几位数字当作偏移量,在散列表里
查找表元(具体取几位,得看当前散列表的大小)。若找到表元为空,异常KeyError,不为空,表元里会有一对 found_key:found_value。这时候 Python 会检验 search_key == found_key 是否为真,如果它们相等的话,就会返回 found_value。如果两个值不匹配,则是散列冲突。
而散列表本
身的索引又只依赖于这个数字的一部分。为了解决散列冲突,算法会在散列值中另外
再取几位,然后用特殊的方法处理一下,把新得到的数字再当作索引来寻找表元。
若这次找到的表元是空的,则同样抛出 KeyError;若非空,或者键匹配,则返回这
个值;或者又发现了散列冲突,则重复以上的步骤。
另外在插入新值时,Python 可能会按照散列表的拥挤程度来决定是否要重新分配内存
为它扩容。如果增加了散列表的大小,那散列值所占的位数和用作索引的位数都会随
之增加,这样做的目的是为了减少发生散列冲突的概率。
Python 会设法保证大概还有三分之一的表元是空的,所以在快要达到这个阈值的时
候,原有的散列表会被复制到一个更大的空间里面。
- dict的散列实现导致的结果
1.key必须是可hash的,所有不可变类型都是可哈希的故可作为键,可变类型不可哈希即不可作为键,如列表,字典类型。
2.在内存消耗上是巨大的,由于字典使用了散列表,而散列表又必须是稀疏的,这导致它在空间上的效率低下。
3.key查询很快,hash表空间换时间。
4.key的排列顺序,取决于添加顺序,并且当dict添加新数据,原有的排列可能会被打乱,因为Python 会设法保证大概还有三分之一的表元是空的,所以在快要达到这个阈值的时
候,原有的散列表会被复制到一个更大的空间里面。这时候重新hash导致排列顺序改变。
5.由此可知,不要对字典同时进行迭代和修改。如果想扫描并修改一个字典,最好分成
两步来进行:首先对字典迭代,以得出需要添加的内容,把这些内容放在一个新字典
里;迭代结束之后再对原有字典进行更新。
集合中的散列表
集合的实现和dict一样,集合的元素就相当于dict中的key,只不过集合没有散列表指向的value。
其特点:
- 集合里的元素必须是可散列的
- 集合很消耗内存
- 可以很高效地判断元素是否存在于某个集合
- 元素的次序取决于被添加到集合里的次序
- 往集合里添加元素,可能会改变集合里已有元素的次序
leason | 博客
- Python字典集合数据结构深入理解
- python 数据结构六 之 字典与集合
- Python中列表、字典、元组、集合数据结构整理
- Python基本数据结构之元组、集合与字典
- Python数据结构中列表,字典,元组,集合的总结
- Python中列表/元组/集合/字典的理解
- 理解Python中列表,元组,字典,集合的区别
- python字典和集合
- Python字典和集合
- python 字典/集合操作
- Python字典和集合
- python <字典 集合>
- Python字典和集合
- **PYTHON** 字典和集合
- Python字典和集合
- python学习-集合、字典
- python字典、集合
- Python [集合 字典]
- codevs 2604 舞会邀请 tarjan
- SpringMVC重要接口(二)HandlerMethodReturnValueHandler
- 使用OpenCV进行目标检测的注意事项
- 0基础lua学习(十一)table
- (递归)逆波兰表达式
- Python字典集合数据结构深入理解
- object
- LitePal使用UUID作为主键
- (Neighbourhood Components Analysis) NCA 近邻成分分析的学习
- caffe编译
- BigDecimal加减乘除运算
- 广义表链表表示的复制删除比较运算的非递归实现(c++)
- C语言 宏的使用 让一个数的二进制奇数位与偶数位互换
- 宏基因组实战4.基因注释Prokka