为什么std :: list具有remove和remove_if函数

时间:2019-06-12 22:41:44

标签: c++ algorithm

为什么std :: list具有remove和remove_if函数?这似乎重复了相同名称的算法功能的行为。如果remove和remove_if有意义,为什么不找到find和if_if?

3 个答案:

答案 0 :(得分:2)

这是因为给定std::list的性质(或更准确地说,是标准强制实施的可能),因此像std::removestd::remove_if这样的标准算法在其上使用时效率低下。 / p>

std::list的实现必须满足一些要求,这实际上迫使它必须基于节点,并与指针结构链接。

此实现有其缺点。例如,它不允许使用随机访问迭代器,因此std::sort根本无法使用,因为它需要随机访问。这是极端的情况。有一些有效的算法可以与std::list可能实现的特定性质一起工作,并且在成员std::list::sort中使用它们。尽管std::sort 可以使用相同的实现,但其他方案可能会导致性能下降。

不太极端的情况是remove情况。标准std::removeerase成员函数(擦除删除惯用语)配对是一种处理删除元素的好方法……除非内部实现使这些操作变得昂贵。在std::list上,std::remove加上对erase的幼稚调用将平均需要O(n)(其中n等于列表的size)操作。通过利用内部实现,可以大大简化此操作(在这种情况下,可能的实现中使用指针操作)。如果您可以直接访问要删除的元素,则此操作将变为O(1)

那么-std::findstd::find_if怎么了?问题是std::list没有其他选择可以从其内部实现中受益。 可以成为成员findfind_if,但它们与<algorithm>版本非常相似,因此无需介绍它们。 / p>

答案 1 :(得分:2)

首先,它们具有不同的语义。 std::list::remove_if删除删除的元素,而std::remove_if不会删除。 std::remove_if还要求容器元素是MoveAssignable,而std::list::remove_if仅要求容器元素是Erasable。

两者之间实际上没有 complexity 差异(它们都是O(n)),但是std::remove_if的速度可能慢大约两倍,因为需要使用两个来遍历列表独立的指针而不只是一个指针-在大多数现代CPU上遍历列表是一项相当昂贵的操作。如果容器元素类型的移动操作昂贵,则可能会另外降低std::remove_if的速度。

答案 2 :(得分:1)

在这种情况下,成员函数效率更高,即使通用函数确实在<algorithm>上起作用,也应该比std::list中更通用的成员函数优先。
原因是std::list允许O(1)复杂性在任何地方删除和插入单个元素,而成员函数则利用了这一点。