一尘不染

删除/删除多个std :: vector元素同时保留原始顺序的最有效方法?

algorithm

我有一个std::vector<int>和第二个容器,用于存放此向量的迭代器或索引(没有键,我想不断访问元素)以进行删除。假设我有一个1000个元素的向量,并想擦除200个元素。在删除操作之后,未删除元素的顺序应与之前相同。

我在问题的第一个版本中还错过了另一件事: 值是唯一的 。他们是身份。

您将如何以安全的方式(关于stl规则)和有效的方式(对矢量的决定是最终决定)来做到这一点?

*我想到的 *可能性方法

  • 所述 擦除remove惯用法 (http://en.wikipedia.org/wiki/Erase-remove_idiom):最初为其中满足条件(包括直链的搜索)的元素的删除,但我认为有尺寸1这种方法可能是范围习惯于已经给定的迭代器和伪条件。 问题:是否保留元素的原始顺序,并且比最后一种方法性能更高?
  • 循环遍历索引,并使用来擦除元素,vector.erase(vector.begin()+index+offset)同时保持将索引删除在容器中以计算偏移量。可以使用std::lower_boundn个已删除元素的容器为每个删除迭代确定此偏移量。 问题:由于随机位置删除,很多用于获取偏移量的binary_searches和很多移动操作。
  • 目前,我正在执行以下操作:获取要删除元素的所有迭代器。根据向量中的位置以降序对它们进行排序,然后使用循环遍历它们以进行最终删除vector.erase。现在,我没有使任何迭代器无效,除了删除本身之外,没有向量重新排列操作。 问题:很多排序

那么,您将如何解决呢?有什么新想法吗?有什么建议吗?

感谢您的输入。

萨沙

编辑/更新/拥有结果: 我实现了KennyTM也提到过的“ 擦除-删除”惯用语 ,它的 谓词基于boost ::
dynamic_bitset中的查找,
并且 速度非常快 。此外,我尝试了 PigBen的移动和截断方法 (Steve
Jessop也提到过),该方法也正在访问while循环中的位集。就我的数据而言,两者似乎同样快。我尝试删除1000个元素中的100个(无符号整数),这100次删除了1M次,没有明显的区别。因为我认为基于stl的“擦除-
删除”惯用法有点“自然”,所以我选择了这种方法(KennyTM也提到了这种说法)。


阅读 515

收藏
2020-07-28

共1个答案

一尘不染

其中<algorithm>有一个remove_if函数,将所有未删除的值压缩到前面,以保持顺序。如果那200个元素可以完全由值而不是索引确定,则此方法有效。

这实际上是您已链接到的删除删除惯用语。remove_if可以保证执行O(N)比较(最多进行O(N)复制),这比排序(O(N log
N))更有效,尽管如果索引为,您的最后一个选择实际上并不需要排序根据值确定(在复印时只需反向扫描即可)。

不过,使用remove_if(如果可以)比其他两个选项要好,因为已经为您编写了实现,因此发生逻辑错误的可能性较小,并且可以更好地传达 要做什么
(而不是 如何 做)。

2020-07-28