根据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)中完成它。
答案 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突然退出,否则这种情况将会发生。