在某个位置插入列表的成本/复杂性是多少?

时间:2014-11-22 03:06:30

标签: python list time-complexity

在Python中,listlist.insert(i, x)来“在给定位置插入项目。”。在C ++中,还有一个list。在C ++中,在任何地方插入元素的成本/复杂度是O(1)。对于Python列表是否相同?如果没有,可以使用其他任何东西在Python中获得O(1)插入时间吗?

4 个答案:

答案 0 :(得分:14)

<强>列表

“平均情况”假定随机均匀生成参数。

在内部,列表表示为数组;最大的成本来自于超出当前分配大小(因为一切都必须移动),或者在开头附近的某处插入或删除(因为之后的所有内容都必须移动)。如果需要在两端添加/删除,请考虑使用collections.deque。

enter image description here

因此,在给定位置插入元素将始终具有 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是瓶颈。在这种情况下,您必须考虑使用不同的数据结构。