在Python中,list有list.insert(i, x)
来“在给定位置插入项目。”。在C ++中,还有一个list。在C ++中,在任何地方插入元素的成本/复杂度是O(1)。对于Python列表是否相同?如果没有,可以使用其他任何东西在Python中获得O(1)插入时间吗?
答案 0 :(得分:14)
<强>列表强>
“平均情况”假定随机均匀生成参数。
在内部,列表表示为数组;最大的成本来自于超出当前分配大小(因为一切都必须移动),或者在开头附近的某处插入或删除(因为之后的所有内容都必须移动)。如果需要在两端添加/删除,请考虑使用collections.deque。
因此,在给定位置插入元素将始终具有 O(n)的时间复杂度,因为插入方法和切片都有时间 O(n)和 O(k)的复杂性。 只有追加在列表末尾插入的 O(1)时间复杂度。 来自Python Wiki
Lists:
Complexity
Operation | Example | Class | Notes
--------------+--------------+---------------+-------------------------------
Index | l[i] | O(1) |
Store | l[i] = 0 | O(1) |
Length | len(l) | O(1) |
Append | l.append(5) | O(1) |
Clear | l.clear() | O(1) | similar to l = []
Slice | l[a:b] | O(b-a) | l[1:5]:O(l)/l[:]:O(len(l)-0)=O(N)
Extend | l.extend(...)| O(len(...)) | depends only on len of extension
Construction | list(...) | len(...) | depends on lenghth of argument
check ==, != | l1 == l2 | O(N) |
Insert | l[a:b] = ... | O(N) |
Delete | del l[i] | O(N) |
Remove | l.remove(...)| O(N) |
Containment | x in/not in l| O(N) | searches list
Copy | l.copy() | O(N) | Same as l[:] which is O(N)
Pop | l.pop(...) | O(N) |
Pop | l.pop() | O(1) | same as l.pop(-1), popping at end
Extreme value | min(l)/max(l)| O(N) |
Reverse | l.reverse() | O(N) |
Iteration | for v in l: | O(N) |
Sort | l.sort() | O(N Log N) | key/reverse doesn't change this
Multiply | k*l | O(k N) | 5*l is O(N): len(l)*l is O(N**2)
来自here
答案 1 :(得分:14)
Python语言没有指定此类操作的实现,因此不同的实现可能具有不同的行为。对于CPython,list.insert
的复杂度为O(n),如this useful wiki page所示。我不知道任何类似列表的结构,在任意索引处插入O(1)性能。 (dict在平均情况下给出O(1)插入性能,但不是有序的,并且不强制执行连续的索引序列。)blist
库提供具有O(log n)的优化列表类型插入
答案 2 :(得分:3)
不,它的复杂程度不同。根据Python的官方Time Complexity页面 1 ,使用list.insert
始终具有O(n)
(线性)复杂性。
此外,Python列表与C ++列表不完全相同。事实上,如果有的话,Python列表更像C ++ std::vector
。
1 那么,CPython的官方页面。我不知道其他实现,如IronPython或Jython。
答案 3 :(得分:0)
Python是一种语言。存在多个实现,并且它们可能具有不同的列表实现。因此,在不查看实际实现的代码的情况下,您无法确定列表的实现方式以及它们在特定情况下的行为方式。
我敢打赌,对列表中对象的引用存储在连续的内存中(当然不是链接列表......)。如果确实如此,那么使用x.insert插入将导致插入元素后面的所有元素被移动。这可以通过硬件有效地完成,但复杂性仍然是O(n)。
对于小列表,bisect操作可能比x.insert花费更多时间,即使前者是O(log n)而后者是O(n)。但是,对于长列表,我猜测x.insert是瓶颈。在这种情况下,您必须考虑使用不同的数据结构。