python中dict.clear()的时间复杂度是O(1)如何?

时间:2018-11-22 20:44:05

标签: python dictionary time-complexity python-internals

根据https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt,dict.clear()的时间复杂度为O(1)。

据我所知,dict.clear()与分配dict = {}不同,因为dict.clear()更改了相同的dict,而dict = {}创建了新的dict。

现在,如果dict.clear()正在清除同一个dict对象,那么它将如何在O(1)中完成它。

2 个答案:

答案 0 :(得分:4)

为何声称它为O(1)的一些理由:

clear()方法实际上只是将内部字典结构分配给新的空值(如source所示)。看似O(n)的部分是减少了引用计数和其他与GC相关的内容的结果。但这纯粹是CPython使用的GC方法的功能(即引用计数);您可以设想不同的方法,这些方法不需要像这样的显式清理,也可以在以后进行清理(甚至摊销)的地方。由于理想情况下,clear()的时间复杂度不应取决于基础的GC方法,因此将省略所有与GC相关的部分,使其变为“ O(1)”。 IMO这主要是一个定义性论据,而不是其他任何论点,但这至少是有理由的。

答案 1 :(得分:3)

我首先想到dict.clear只是执行了一些引用减少操作,以使垃圾收集器执行脏的非O(1)工作,但是看着source code(感谢timgeb提供了链接)似乎并非如此:

   oldvalues = mp->ma_values;
    if (oldvalues == empty_values)
        return;
    /* Empty the dict... */
    dictkeys_incref(Py_EMPTY_KEYS);
    mp->ma_keys = Py_EMPTY_KEYS;
    mp->ma_values = empty_values;
    mp->ma_used = 0;
    mp->ma_version_tag = DICT_NEXT_VERSION();
    /* ...then clear the keys and values */
    if (oldvalues != NULL) {
        n = oldkeys->dk_nentries;
        for (i = 0; i < n; i++)
            Py_CLEAR(oldvalues[i]);

我看到的是,如果字典中有值,则执行循环以减少对这些值的引用并将指针设置为NULL。似乎是O(n)而不是O(1),因为它取决于值的数量。

当您分配给像d = {}这样的新字典时,它就是O(1),但是当垃圾回收器不再被引用时,它必须删除旧对象。分配时可能不正确,但是除非python突然退出,否则这种情况将会发生。