繁体   English   中英

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

[英]What is the time complexity of std::deque::erase function?

在这里,它说明了时间的复杂性:

线性删除的元素数(破坏)。 另外, 取决于特定的库实现 ,在位置与双端队列的两端之间的元素数量上,最多需要额外的线性时间。

从第一句话我知道,如果要删除双端队列中的任何数字,则最坏情况下的复杂度将为O(1)。

现在第二句话使我感到困惑。 取决于特定的库实现是什么意思? 我正在使用STL库,该库与GCC编译器一起提供。 在我的情况下,如何学习此函数的正确时间复杂度?

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

如果必须从双端队列中删除n项目,通常需要使用remove/erase习惯用法。

您从std::remove开始删除n项本身。 这基本上将您的集合分为两部分:一开始是您没有删除的部分,另一部分是您不再关心的内容。

它返回一个指向这两个边界的迭代器。 然后,您可以从那里擦除到结尾(一次),以摆脱不再关心的项目。

std::remove基本上执行了我认为的“波纹复制”操作-从头到尾遍历整个集合,当找到要删除的项目时,它会找到要保留的下一个项目,并且将其复制到要删除的文件1

如果您不需要维护所保存物品的顺序,则通常可以进一步提高速度。 从集合的开头开始,找到您要删除的项目(即,您当前要erase )。 年底开始找到你想要保存项目(即,一个你不会 erase )。 交换这两个项目,然后继续“向内”搜索,直到两个位置相遇。 现在,您要删除的所有项目都在集合的末尾。 您可以在O(1)中删除所有它们。

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


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

cplusplus.com涵盖了C ++标准库,而不是原始的STL。 C ++ stdlib包含了大部分 STL,并且它具有几种实现方式,这些实现通常(如果不是始终如此)从STL代码派生而来,但可以通过各种方式对其进行更改。 实际上,GCC实现是对STL + GNU的修改。 根据该标准, deque中的erase可以是线性的。

如果您想了解实现过程中此操作的复杂性,请阅读手册 (尽管我在任何地方都找不到deque ),阅读源代码或配置文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM