我正在编写一个简单的Python程序。
我的程序似乎受到线性词典的访问, 即使算法是二次的,它的运行时间也呈指数增长 我使用字典来记忆值。这似乎是一个瓶颈。
我正在散列的值是点的元组。
每个点是:(x,y),0 <= x,y <= 50
字典中的每个键是:2-5点的元组:((x1,y1),(x2,y2),(x3,y3),(x4,y4))
键的读取次数比写入次数多很多次。
我是否认为python dicts受到这些输入的线性访问时间的影响?
据我所知,套装保证了对数访问时间 如何在Python中使用集合(或类似的东西)模拟dicts?
编辑根据请求,这是memoization函数的(简化)版本:
def memoize(fun):
memoized = {}
def memo(*args):
key = args
if not key in memoized:
memoized[key] = fun(*args)
return memoized[key]
return memo
答案 0 :(得分:39)
见Time Complexity。 python dict是一个hashmap,因此如果hash函数不好并导致大量冲突,则最坏的情况是O(n)。然而,这是一种非常罕见的情况,其中添加的每个项目都具有相同的哈希值,因此被添加到同一个链中,对于主要的Python实现来说,极不太可能。平均时间复杂度当然是O(1)。
最好的方法是检查并查看正在使用的对象的哈希值。 CPython Dict使用int PyObject_Hash (PyObject *o),相当于hash(o)
。
经过快速检查后,我还没有设法找到两个散列为相同值的元组,这表明查找是O(1)
l = []
for x in range(0, 50):
for y in range(0, 50):
if hash((x,y)) in l:
print "Fail: ", (x,y)
l.append(hash((x,y)))
print "Test Finished"
CodePad(24小时可用)
答案 1 :(得分:3)
你不正确。 dict
访问权限不太可能是您的问题。几乎可以肯定是O(1),除非你有一些非常奇怪的输入或非常糟糕的散列函数。粘贴应用程序中的一些示例代码以获得更好的诊断。
答案 2 :(得分:3)
如果提供示例代码和数据,建议会更容易。
访问字典不太可能是一个问题,因为该操作是O(1) on average, and O(N) amortized worst case。内置散列函数可能会遇到数据冲突。如果您遇到内置散列函数问题,可以自行提供。
Python的字典实现 降低了平均复杂度 字典查找到O(1)by 要求关键对象提供 “哈希”功能。这样的哈希函数 获取关键对象中的信息 并用它来产生一个整数, 称为哈希值。这个哈希值 然后用于确定哪个 “桶”这个(键,值)对应该 被放入。
您可以覆盖类中的__hash__方法来实现这样的自定义哈希函数:
def __hash__(self):
return hash(str(self))
根据您的数据实际情况,您可能能够提供一个比标准函数具有更少冲突的更快哈希函数。但是,这不太可能。有关详细信息,请参阅Python Wiki page on Dictionary Keys。
答案 3 :(得分:2)
我的程序似乎受到字典线性访问的影响,即使算法是二次方,它的运行时间也呈指数级增长。
我使用字典来记忆值。这似乎是一个瓶颈。
这是您的记忆方法中存在错误的证据。
答案 4 :(得分:1)
正如其他人所指出的那样,访问Python中的dicts很快。鉴于它们的核心作用,它们可能是语言中最好的数据结构。问题出在其他地方。
你记得有多少元组?你考虑过内存占用吗?也许你把所有时间花在内存分配器或分页内存上。
答案 5 :(得分:1)
回答您的具体问题:
Q1:“”“我是否认为python dicts受到这些输入的线性访问时间的影响?”“”
A1:如果你的意思是平均查询时间是O(N),其中N是dict中的条目数,那么很可能你错了。如果你是对的,那么Python社区非常想知道你在什么情况下是正确的,这样可以减轻问题或者至少可以警告这个问题。 “样本”代码和“简化”代码都不是有用的。请显示重现问题的实际代码和数据。代码应该用诸如dict项的数量和每个P的dict访问次数之类的东西进行检测,其中P是密钥中的点数(2 <= P <= 5)
Q2:“”据我所知,套装保证了对数访问时间。 如何在Python中使用集合(或类似的东西)模拟dicts?“”“
A2:集合在什么情况下保证了对数访问时间? Python实现没有这样的保证。最近的CPython版本实际上使用了一个缩减的dict实现(仅键,没有值),所以期望是平均O(1)行为。你怎么能用任何语言的集合或类似的东西模拟dicts?简短回答:如果你想要dict.has_key(key)
之外的任何功能,那么极其困难。