【发布时间】:2020-03-25 13:56:44
【问题描述】:
我正在写一篇关于 Python list.clear() 方法的博文,其中我还想提一下底层算法的时间和空间复杂度。我预计时间复杂度为 O(N),遍历元素并释放内存?但是,我发现了一个article,其中提到它实际上是一个 O(1) 操作。然后,我在 CPython implementation 中搜索了该方法的源代码,发现了一个我认为是 list.clear() 的实际内部实现的方法,但是我不确定它是否是。以下是该方法的源代码:
static int
_list_clear(PyListObject *a)
{
Py_ssize_t i;
PyObject **item = a->ob_item;
if (item != NULL) {
/* Because XDECREF can recursively invoke operations on
this list, we make it empty first. */
i = Py_SIZE(a);
Py_SIZE(a) = 0;
a->ob_item = NULL;
a->allocated = 0;
while (--i >= 0) {
Py_XDECREF(item[i]);
}
PyMem_FREE(item);
}
/* Never fails; the return value can be ignored.
Note that there is no guarantee that the list is actually empty
at this point, because XDECREF may have populated it again! */
return 0;
}
我可能是错的,但在我看来确实像 O(N)。另外,我发现了一个类似的问题here,但那里没有明确的答案。只是想确认list.clear() 的实际时间和空间复杂度,也许还有一点支持答案的解释。任何帮助表示赞赏。谢谢。
【问题讨论】:
-
当您使用
timeit模块为一个包含一万个项目和一个包含一千万个项目的列表计时清除方法时发生了什么? -
@wwii 使用
timeit对list.clear计时是不可能的,因为timeit运行代码的多次迭代,而list.clear清除了列表,因此下一次迭代将在空的列表。如果你试图通过在每次迭代中创建一个新列表来解决这个问题,你就会混淆测量,因为创建列表肯定是 O(n)。 -
直接观察
list.clear复杂性的方法是测量list.clear的一次执行的时间(尽可能精确地使用时钟)在大小为一千个元素的列表上,然后是一万、十万、百万等。有了足够数量的元素,时间将变得可测量,并且线性显示。 -
@user4815162342 - 你只需要告诉 timeit 执行一个 loop。 - 它应该给出足够的结果。
-
@wwii 当然,这也可以,只是需要注意不要使用默认设置(在大多数情况下这是相当合理的)。
标签: python time-complexity cpython space-complexity