在学校我了解到一个链表包含一个指向列表中下一个元素的指针的元素,链表的缺点是找到大小有线性复杂性,因为你必须经历每个元素和计数。但是我注意到在C ++ 11中,std :: list.size()具有恒定的复杂性。这怎么可能?
答案 0 :(得分:7)
多么容易。它缓存它。你可以缓存任何东西,只要你不让它变得无效。保持缓存有效有多难? 1
为什么在C ++ 11中?这是什么意思?
在C ++ 11之前,std::list::size
没有提到它有多复杂。
某些实现保留了一个大小字段,其他实现没有。保持大小字段的优点是.size()
是恒定时间;不是的优点是可以在一定时间内完成一些拼接操作。
在跟踪size()
时,拼接操作需要计算拼接的节点。这使它无法保持恒定时间,并且变为O(n)。
C ++ 11决定,因为所有其他.size()
函数都是常量时间,所以它们会强制list
也具有恒定的时间大小。这打破了一些std::list
的ABI,并阻止了不断的时间拼接。
1 计算机编程存在两个难题。命名事物,缓存失效,以及关闭一个错误。
答案 1 :(得分:6)
只要保留一个成员变量,只要添加或删除元素就会更新。或者,如果将两个列表合并在一起,只需将它们的计数加在一起。
然后你不必遍历整个列表来计算元素。