【问题标题】:Removing multiple elements from stl list while iterating迭代时从stl列表中删除多个元素
【发布时间】:2015-06-30 10:22:03
【问题描述】:

这与Can you remove elements from a std::list while iterating through it? 不同。我的情况不同。

假设我有一个这样的列表。

1  2  3  1  2  2  1  3

我想以这样的方式迭代这个 stl 列表 当我第一次遇到元素 X 时,我会做一些活动,然后我需要删除该列表中的所有元素 X 并继续迭代。什么是在 C++ 中执行此操作的有效方法。

我担心当我执行删除或擦除时,我会使迭代器无效。如果它只有一个元素,那么我可能会增加迭代器然后擦除。但在我的场景中,我需要删除/擦除所有事件。

一直在想这样的事情

while (!list.empty()) {
   int num = list.front();
   // Do some activity and if successfull
   list.remove(num);
   }

不知道这是不是最好的。

【问题讨论】:

  • @dwcanillas 这会使未知的迭代器集失效。
  • @PSIAlt 抱歉,我以为我们在谈论向量,而不是列表。
  • 迭代时是否必须删除,或者您可以在迭代之前修改列表吗?在后一种情况下,您可以使用list::unique 仅保留您需要的唯一元素。
  • 是的,我需要从列表的前面进行活动。 (它的一种队列)。
  • 来自 list::unique 文档:“请注意,只有当它与紧接在其前面的元素比较时,它才会从列表容器中删除。因此,此函数对于排序列表特别有用。” OP 的列表未排序。

标签: c++ list stl erase removeall


【解决方案1】:

保存一组看到的数字,如果您遇到集合中的数字,请忽略它。你可以这样做:

list<int> old_list = {1, 2, 3, 1, 2, 2, 1, 3};
list<int> new_list;
set<int> seen_elements;
for(int el : old_list) {
  if (seen_elements.find(el) == seen_elements.end()) {
    seen_elements.insert(el);
    new_list.push_back(el);
  }
}
return new_list;

这将只处理每个值一次,new_list 将只包含old_list 中每个元素的第一个副本。这在 O(n*log(n)) 中运行,因为每次迭代都执行一个集合查找(您可以通过使用哈希集来实现这个 O(n))。这比您的方法运行的 O(n^2) 好得多。

【讨论】:

    猜你喜欢
    • 2018-07-18
    • 1970-01-01
    • 2016-07-19
    • 2011-04-02
    • 2020-11-25
    • 2016-11-21
    • 2013-01-23
    • 2010-12-07
    相关资源
    最近更新 更多