【问题标题】:deleting a single occurrence of a number in a vector when having its multiple occurrence while traversing in reverse反向遍历时在向量中多次出现时删除单个出现的数字
【发布时间】:2014-01-23 23:40:52
【问题描述】:

我有一个整数向量,我正在反向遍历。我需要在其中搜索一个元素并在遍历向量时删除它的第一次出现。我正在使用以下函数并出现分段错误

for(i=num.end()-1;i!=num.begin()-1;i--)
{
    tmp=binary(*i);
    if(tmp!=num.end())
        {num.erase(i);num.erase(tmp);res++;}
}

这里的函数二进制返回一个迭代器,如果要使用擦除函数的语句,其值肯定小于i。

我使用了以下链接:- How to traverse vector from end to start?Erasing elements from a vector

但他们建议使用 std::remove 和 std::remove_if 函数来擦除所有出现的值。

【问题讨论】:

  • 从向量中删除后无法继续迭代。您应该在删除后重置迭代器。
  • 您能否通过一个示例详细说明如何做到这一点?

标签: c++ algorithm vector


【解决方案1】:

编辑:我错了,你的设计有缺陷。

我忽略的问题:注意num.erase(x) 使x 之后的元素的引用和迭代器无效。这意味着num.erase(i);num.erase(tmp);tmp < i 时有效,但也意味着i 之后将无效。所以,在循环的下一次迭代中,你的循环迭代器将失效!

如果您只打算擦除这两个元素,则应在擦除它们后退出循环。如果您打算在端到端扫描中删除多个项目,则需要找到某种方法将循环指针推进到最早删除点之前的点。 (不过,您还应该注意,从std::vector<> 的中间删除多个项目是低效的——通常从长度为 N 的向量中每次删除需要 O(N))。您也可以退出循环并从头开始(我认为@SHR 的意思是“重置迭代器”)。

如果您不能执行上述任何操作,则需要其他类型的容器,例如 std::list<>erase() 不会使其余元素的迭代器失效。此外,这些删除是 O(1) (虽然你失去了快速随机访问......)


如果binary() 的行为方式与您所说的一样,那么您的意图似乎是正确的:erase()ing 来自std::vector<> 的元素应该保留对已删除元素之前元素的引用和迭代器。

问题可能出在其他地方。如果您发布的代码是您程序中的逐字代码,则您的 if 语句中存在格式错误:

if(tmp!=num.end())
    num.erase(i);num.erase(tmp);res++;

请注意,实际受if 条件影响的唯一语句是num.erase(i);——其余语句将无条件执行。具体来说,如果tmp==num.end(),它仍然会执行num.erase(tmp),可能会导致分段错误......

可能的最小解决方法是在三个语句周围添加花括号:

if(tmp!=num.end())
    {num.erase(i);num.erase(tmp);res++;}

【讨论】:

  • 其实再看一遍,其实你的设计有问题。我会更新我的答案...
猜你喜欢
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 2014-05-01
  • 1970-01-01
相关资源
最近更新 更多