2021.9.10 dict的相关知识(累计更新)
一、 dict的内部原理
1. 哈希表
python dict的内部数据结构是哈希表,哈希表其实是一个稀疏数组(总是有空白元素的数组成为稀疏数组)。它通过把关键码值(key-value)映射到表中的一个位置来访问记录,查找的速度十分快,理论上的世界复杂度是O(1)。因为哈希表的本质是数组,因此它在地址上是连续的,数组中每一个元素称为一个箱子(bin)或者表元(bucket),箱子中放键值对。
2. 哈希函数
哈希函数也称为散列函数,是hash表的映射函数。它可以将任意长度的输入变换为固定长度的输出。该输出值就是哈希值/散列值,即元素在哈希表中的存储位置。但是很难找到一个不产生冲突的哈希函数,所以我们只能选择恰当的哈希函数,使冲突尽可能少的产生。常用的哈希函数有:MD4、MD5、SHA1(安全散列算法)。
解决哈希冲突的方法有:
- 开放定址法:
H
i
=
(
H
(
K
e
y
)
+
d
i
)
M
o
d
m
H_i=(H(Key)+d_i)Mod m
Hi?=(H(Key)+di?)Modm,其中m是散列表的长度,d是一个序列,根据序列不同,可分为:线性探测再散列、平方探测再散列随机探测再散列. 对应的d分别为d=[1,2,3,4,…,s], d=[
1
2
,
?
1
2
,
2
2
,
?
2
2
,
.
.
.
.
,
s
2
,
?
s
2
1^2,-1^2,2^2,-2^2,....,s^2,-s^2
12,?12,22,?22,....,s2,?s2], d为伪随机数列。 - 链地址法
链地址法也称为拉链法,将产生冲突的值以链表的形式连起来,采用它的优势是,处理冲突很简单,没有堆积现象。其次拉链法中的链表节点,是动态申请的。所以很适合表长不确定的情况。
3. python的dict原理
这里有一个好的参考资料 链接中的文章出现了一个例子: 例子分析如下:
- 在这里例子中有两个函数很关键:hash函数和eq函数。HashTester的字典中只有一个元素是因为两个对象具有完全一样的key值和hash值。而HashTester的字典中有两个元素是因为没有重写_eq__方法,导致两者的键key的不一样的,尽管两者具有一样的hash值。
总结相关知识:
- 同一个key对应的地址应该相同。因此只有不可变数据类型才可以做为key,而list不可变数据类型就不可以作为key。一个对象的hash值是使用其函数__hash__计算的,可变数据类型没有该函数。
a= {}
#错误,因为list可变 list is unhashable
a[[1,3]]="g"
# 正确,因为tuple不可变
a[(1,3)]="g"
- python中的两个函数很重要,hash函数和eq函数。其中eq用于判断两个对象是否相同,而hash是计算对象的hash值。关于自定义类型中的eq和hash的相关知识见链接(这部分内容我还没有完全理解)
二. dict和list、dict和set
1.dict和list的关系
假设我们要在一本字典中查找一个汉字,在list中查找相当于从字典第一页开始翻,而dict相当于先根据偏旁部首等找到该字对应的页码,然后一下就翻到了。dict就是根据key来作为索引得到value存储的位置的
2.set和dict的关系
set和dict类似,也有一组key的集合,但不存储value。由于key不能重复,所有在set中没有重复的key。更多set的例子见 set的知识合集。
三. dict的函数
还没写呢
|