Time complexity of accessing a Python dict
我正在编写一个简单的python程序。
我的程序似乎受到了字典的线性访问,即使算法是二次型的,它的运行时间也呈指数增长。我用字典来记忆价值观。这似乎是一个瓶颈。
我要散列的值是点的元组。每个点是:(x,y),0<=x,y<=50字典中的每个键是:一个2-5点的元组:((x1,y1),(x2,y2),(x3,y3),(x4,y4)
读钥匙的频率比写钥匙的频率高很多。
对于这种输入,python dict会遭受线性访问时间,这是正确的吗?
据我所知,集合有保证的对数访问时间。如何在python中使用集合(或类似的东西)模拟dict?
根据要求进行编辑,以下是记忆功能的(简化)版本:
1 2 3 4 5 6 7 8 | def memoize(fun): memoized = {} def memo(*args): key = args if not key in memoized: memoized[key] = fun(*args) return memoized[key] return memo |
见时间复杂性。python dict是一个散列映射,因此,如果散列函数不好并导致大量冲突,那么它的最坏情况是o(n)。但是,这是非常罕见的情况,因为添加的每个项都具有相同的哈希值,因此添加到同一个链中,这对于主要的Python实现来说是极不可能的。平均时间复杂性当然是O(1)。
最好的方法是检查并查看正在使用的对象的哈希值。cpython dict使用int pyobject_hash(pyobject*o),它相当于
在快速检查之后,我还没有找到两个哈希值相同的元组,这表明查找是O(1)
1 2 3 4 5 6 7 | 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" |
代码板(24小时可用)
如果您提供示例代码和数据,那么就更容易提出建议。
访问字典不太可能是一个问题,因为该操作平均为O(1),而O(n)是分摊的最坏情况。内置的哈希函数可能会与您的数据发生冲突。如果您遇到内置哈希函数的问题,可以提供自己的哈希函数。
Python's dictionary implementation
reduces the average complexity of
dictionary lookups to O(1) by
requiring that key objects provide a
"hash" function. Such a hash function
takes the information in a key object
and uses it to produce an integer,
called a hash value. This hash value
is then used to determine which
"bucket" this (key, value) pair should
be placed into.
您可以覆盖类中的哈希方法来实现如下自定义哈希函数:
1 2 | def __hash__(self): return hash(str(self)) |
根据数据的实际外观,您可能能够找到比标准函数冲突更少的更快的哈希函数。然而,这不太可能。有关更多信息,请参见字典键上的python wiki页面。
你不正确。
My program seems to suffer from linear access to dictionaries, its run-time grows exponentially even though the algorithm is quadratic.
I use a dictionary to memoize values. That seems to be a bottleneck.
这是你记忆方法中的一个错误的证据。
要回答您的特定问题:
问题1:"是否正确,python dict使用此类输入时会出现线性访问时间?"
A1:如果您的意思是平均查找时间是O(N),其中N是dict中的条目数,那么您很可能是错的。如果您是正确的,那么Python社区非常希望知道您在什么情况下是正确的,这样可以减轻或至少警告问题。"示例"代码和"简化"代码都不是有用的。请显示重现问题的实际代码和数据。代码应该使用诸如dict项的数量和每个p的dict访问数之类的东西进行检测,其中p是键中的点数(2<=p<=5)。
问题2:"据我所知,集合有保证的对数访问时间。如何在python中使用集合(或类似的东西)模拟听写?"
A2:集合在什么上下文中保证了对数访问时间?对于Python实现没有这样的保证。最近的cpython版本实际上使用了一个缩减的dict实现(仅限键,没有值),因此期望是平均O(1)行为。你怎么能用任何语言的集合或类似的东西来模拟口述呢?简短的回答:如果您想要除
正如其他人指出的,在Python中访问dict很快。考虑到它们的中心作用,它们可能是语言中最好的涂油数据结构。问题出在别处。
你在记忆多少个元组?你考虑过内存占用吗?也许您将所有的时间都花在内存分配器或分页内存上。