为什么Python花费O(n)时间从列表中删除第一个元素?

时间:2016-06-02 03:40:08

标签: python algorithm list big-o

Python wiki page on time complexity表示删除项目需要花费O(n)时间。 description of the deque class in the documentation of the collections module表示" list个对象会导致pop(0)insert(0, v)操作的O(n)内存移动成本,从而改变大小和基础数据表示的位置"。

为什么列表需要O(n)时间? Isn列出的只是一堆元素,或指向元素的指针,在内存中彼此物理上相邻,以及指向列表开始位置的指针?如果是这样,为什么list类型具有popleft方法,类似于collections.deque中的方法,通过适当增加来删除O(1)时间内的第一个元素列表的开始指针?

我不是要解决任何具体问题。我只是想满足我的好奇心,为什么它是这样设计的。

编辑:以下是我popleft方法的工作原理图:

致电popleft之前:

-------------------------------------------------------------------
|    The   |  quick   |  brown   |   fox    |  jumps   |   over   |
-------------------------------------------------------------------
      ^
      pointer to list

致电popleft后:

-------------------------------------------------------------------
|    The   |  quick   |  brown   |   fox    |  jumps   |   over   |
-------------------------------------------------------------------
                 ^
                 pointer to list

在致电popleft之前,列表的第一个元素是The,第二个元素是quick等。通话结束后,第一个元素的位置现在是未使用的内存(可能留空或由垃圾收集器声明),新的第一个元素是quick,新的第二个元素是brown等。不需要移动大量数据,并且不需要花费O(n)时间。

3 个答案:

答案 0 :(得分:3)

必须保留指向真正列表所在位置的指针,以便正确释放内存。

实际上,通过在这种情况下增加第二个指针可以使remove(0)更快。如果之后发生.add(0, x),只要它大于“内存启动计时器”,就可以通过递减这个“数据启动计时器”来加快速度。

但所有其他操作,我。即对其他索引的插入和删除仍然是O(n),因此不会有太大变化。

只需知道您的操作是什么,以及选择哪种数据结构。

答案 1 :(得分:2)

Python list实际上是一个数组。 deque是一个真实的链接列表。使用错误的术语是Python的错(我没有解释)。 O(n)用于插入和删除对于数组是正常的(因为以下元素需要向上或向下移动),这是获取和设置的O(1)速度的权衡。链接列表在相反的方向上进行类似的权衡:O(1)用于结束时的操作,但O(n)用于中间的任何访问。

答案 2 :(得分:1)

没有理由不能,它只是没有。然而,这是代码的复杂性,而您所面临的问题通常表明您采取了错误的方法。

您可以在包装器类中自己实现此行为,并在您知道它值得的情况下使用它。

那就是something similar has been submitted to PyPy