std :: deque :: erase函数的时间复杂度是多少?

时间:2014-10-05 15:08:34

标签: c++ stl

Here它说明了时间复杂性:

  

线性删除的元素数量(破坏)。另外,取决于特定的库实现,最多可以在位置和双端队列之一之间的元素数量上增加线性时间。

从第一句话我明白,如果你想删除双端队列中的任何数字,最坏的情况就是O(1)。

现在第二句让我感到困惑。取决于特定的库实现意味着什么?我正在使用STL库,与GCC编译器一起提供的库。在我的情况下,如何才能了解此函数的正确时间复杂度?

我需要它是O(1)因为我正在运行O(n)擦除调用,如果std::deque::erase是O(n)我的算法将具有二次复杂度,这是我不能想。

2 个答案:

答案 0 :(得分:2)

如果您必须从双端队列中删除n项,通常需要使用remove/erase成语。

您从std::remove开始删除n项目。这基本上将你的收藏分成两部分:一开始你没有删除的部分,最后一些空间包含你不再关心的东西。

它返回一个指向这两者之间边界的迭代器。然后你可以从那里擦除到最后(一次)去掉你不再关心的物品。

std::remove基本上做了我认为的“涟漪副本”#34; - 它从头到尾遍历集合,当它找到您要删除的项目时,它会找到您要保留的下一个项目,并将其复制到您要删除的项目上 1

如果您不需要维护所保留物品的顺序,您通常可以提高速度。从集合的开头开始,找到您想要删除的项目(即,您当前erase的项目)。从 end 开始,找到您要保留的项目(即, erase)。交换这两个项目,继续搜索"向内"直到两个职位见面。现在,您要删除的所有项目都在集合的末尾。您可以在O(1)中删除所有这些。

理论上,这两者的总体复杂性是相同的 - 都是O(N)。然而,在许多情况下,复制项目相对昂贵(而不仅仅是确定是否保留该项目)。这样可以最大限度地减少复制/移动的项目数量,因此当复制/移动费用昂贵时,可以节省相当多的时间(但是,如前所述,如果其余对象的顺序很重要,则不适合)


  1. 请注意,从C ++ 11开始,这些可以是移动而不是副本(例如,如果你提供移动迭代器)。

答案 1 :(得分:0)

cplusplus.com涵盖了C ++标准库,而不是原始STL。 C ++ stdlib包含most of STL,它有几个实现,通常(如果不总是)派生自STL代码,但可能以各种方式更改它。事实上,GCC实现是STL + GNU修改。根据标准,erase中的deque元素数量可能是线性的。

如果您想在实施中找出此操作的复杂性,请阅读the manual(尽管我无法在任何地方找到deque),请阅读来源或配置文件