Python 如果使用很长的字符串作为键,在Dict中搜索的时间复杂度是多少?
我从python3文档中读到,python使用dict()的哈希表。因此,搜索时间复杂度应为O(1),O(N)为最坏情况。然而,最近我上了一门课,老师说只有当你用int作为键时才会发生这种情况。如果使用长度为L的字符串作为键,则搜索时间复杂度为O(L) 我写了一段代码来测试他的诚实Python 如果使用很长的字符串作为键,在Dict中搜索的时间复杂度是多少?,python,python-3.x,dictionary,hash,hashtable,Python,Python 3.x,Dictionary,Hash,Hashtable,我从python3文档中读到,python使用dict()的哈希表。因此,搜索时间复杂度应为O(1),O(N)为最坏情况。然而,最近我上了一门课,老师说只有当你用int作为键时才会发生这种情况。如果使用长度为L的字符串作为键,则搜索时间复杂度为O(L) 我写了一段代码来测试他的诚实 随机导入 导入字符串 从时间导入时间 将matplotlib.pyplot作为plt导入 def随机字符串(stringLength=10): “”“生成固定长度的随机字符串”“” 字母=字符串。ascii_小写 返
随机导入
导入字符串
从时间导入时间
将matplotlib.pyplot作为plt导入
def随机字符串(stringLength=10):
“”“生成固定长度的随机字符串”“”
字母=字符串。ascii_小写
返回“”。在范围(stringLength)内为i连接(随机选择(字母))
def测试(L):
#L:键的整数长度
N=1000#钥匙数量
d=dict()
对于范围(N)中的i:
d[随机字符串(L)]=无
tic=时间()
对于d.keys()中的键:
d[钥匙]
toc=时间()-tic
tic=时间()
对于d.keys()中的键:
通过
t_idle=time()-tic
t_总计=toc-t_空闲
返回t_总数
L=[i*10000表示范围(5,15)内的i]
ans=[测试(l)中的l]
plt.图()
plt.绘图(L,ans)
plt.show()
结果非常有趣。如您所见,x轴是用作键的字符串的长度,y轴是查询字典中所有1000个键的总时间
有人能解释这个结果吗
请对我温柔一点。如您所见,如果我问这个基本问题,这意味着我没有能力阅读python源代码或相当复杂的内部文档 由于字典是哈希表,在哈希表中查找密钥需要计算密钥的哈希,因此在字典中查找密钥的时间复杂度不能小于哈希函数的时间复杂度 在当前版本的CPython中,如果是第一次对特定字符串对象进行哈希运算,则长度为L的字符串需要O(1)个时间来计算哈希值,如果已计算该字符串对象的哈希值(因为哈希值已存储),则需要O(1)个时间:
>>>从timeit导入timeit
>>>s='b'*(10**9)#长度为10亿的字符串
>>>timeit(lambda:hash,number=1)
0.48574538500002973#半秒
>>>timeit(lambda:hash,number=1)
5.301000044255488e-06#5微秒
这也是在字典中查找关键字所需的时间:
>s='c'*(10**9)#长度为10亿的字符串
>>>d=dict()
>>>timeit(λ:s在d中,数字=1)
0.485215068999167#半秒
>>>timeit(λ:s在d中,数字=1)
4.491000026973779e-06#5微秒
您还需要注意,字典中的键不仅仅是通过其散列查找的:当散列匹配时,它仍然需要测试您查找的键是否等于字典中使用的键,以防散列匹配为假阳性。在最坏的情况下,测试字符串的相等性需要O(L)时间:
s1='a'*(10**9)
>>>s2=‘a’*(10**9)
>>>timeit(lambda:s1==s2,数字=1)
0.2006020820001595
对于长度为L的键和长度为n的字典:
- 如果该密钥不在字典中,并且其哈希已被缓存,则需要0(1)个平均时间来确认该密钥不存在
- 如果密钥不存在且其散列未被缓存,则由于计算散列,需要O(L)个平均时间
- 如果密钥存在,则由于等式测试,无论是否需要计算哈希,都需要O(L)个平均时间来确认它是否存在
- 最坏的情况总是O(nL),因为如果每个哈希冲突,并且字符串除了最后几位都相等,那么必须执行n次缓慢的相等测试
其他时候,应用程序有一个哈希表,其中的键可能会有很大的变化。想象一下,假设有一个散列集,其中键是二进制数据编码视频:一个数据集是旧的标准定义24fps视频剪辑,另一个是8k UHD 60fps电影。插入这些密钥集所需的时间不仅仅是这些密钥数量的比率,因为在密钥散列和比较中涉及的工作量大不相同。在这种情况下,如果您想对不同大小的键的插入时间进行推理,如果没有相关因素,big-O性能分析将是无用的。您仍然可以描述具有相似大小键的数据集的相对性能,只考虑正常的哈希表性能特征。当密钥散列时间可能成为问题时,你可能想考虑你的应用程序设计是否仍然是一个好主意,或者是否你可以使用一组说的文件名而不是原始的视频数据。而不是强迫每个人读代码,试着理解你正在做什么,然后预言什么。