时间复杂度和插入std :: list

时间:2014-03-16 18:19:57

标签: c++ list new-operator time-complexity

在std :: list上插入声称是恒定时间,无论是否 在容器的正面,中间或后面制作。

另一方面,新插入项目的内存获取由处理 标准分配器,它使用operator new。 AFAIK操作员new不保证 有恒定的时间。

当operator new查找堆中的可用空间时,必须确保它 不会覆盖以前分配的内存,因此必须跟踪 已经在堆上分配的内容。我总结说插入 必须至少与列表中已有的元素数量成线性关系。

这种推理有什么问题?


我的问题是:

  • 怎么可能说列表上的插入是不变的 时间,当为每个新节点获取内存时,不保证是恒定时间?

2 个答案:

答案 0 :(得分:3)

注意:重要的是要注意"实际生活时间"而且"时间"谈到潜入时间复杂性时谈到的。当时间复杂性成为主题时,重要的是不要将"时间" 的使用与"毫秒花费在做某事上的事情混淆起来" #34;


什么是恒定时间的定义?

在许多情况下,维基百科通常被认为是一个不好的参考,但在这种情况下(以及许多其他情况),可用的定义是正确的,将有助于描述事物的运作方式。

关于time complexity的文章说明了以下常量时间

  

Wikipedia - Constant Time

     

如果T(n)的值受不依赖于输入大小的值限制,则称算法是恒定时间(也写为O(1)时间)。例如,访问数组中的任何单个元素需要恒定的时间,因为只需要执行一个操作来定位它。


由于插入std::list不依赖于列表中元素的数量,我们说插入是恒定时间;每次插入,无论何时何地,都包含相同数量的基本操作;没有与列表大小有关。



但如果operator new不是O(1)怎么办?

老实说,这并不重要,即使new的复杂性隐含地取决于我们分配了多少先前的实体,我们的 list-insertion 的复杂性将是不变。分配对列表的大小无动于衷。

O(1)常量时间,意味着执行某些操作的时间与任何给定算法中的输入大小无关。即使new不是O(1),我们的插入也是O(1),因为它只描述了自己。

list inseration 中包含的路径包括operator new。由于列表的大小,路径不会改变,路径的复杂性是恒定时间



那我们在处理什么?

Hannibal_Smith中{p> ##c++ at freenode说了一些聪明的东西,我非常喜欢它,我将把它包含在这篇文章中:成本模型是一个指针机器。

尽管句子可能有点误导,但它确实有助于解释插入是O(1)的方式,即使算法的某些部分不是常数时间

从作为仅处理指针的机器的角度来描述插入std::list,从这个角度来看,不能说它只是O(1)。在该算法中完成的分配与算法本身的复杂性无关。

答案 1 :(得分:1)

这是一个非常棘手的问题,已在this thread中详细讨论过。

如果我可以尝试总结一下:标准会做出一些微妙的区分。如果您精确地阅读它,某些操作 确实被指定为“恒定时间”,但std::list插入。它被指定为“常量”(编辑:错误,见下文),“一般容器要求”条款(this draft of the C++ standard中的23.2.1)解释了

  

本条款中的所有复杂性要求仅根据所包含对象的操作次数进行说明。

修改:正如FilipRoséen指出的那样,我错了; std::list插入 被指定为“常数时间”,但我相信一般要求条款仍然适用)。因此,因为列表插入只需要处理单个对象及其邻居,所以它是“常量复杂性”,即使它可能不一定是“常量时间复杂性”,因为没有时间复杂性保证分配

实际上,一个不错的内存分配器在分配的对象数量上是线性的,尽管它可能也不是恒定的时间。