c++ - 从集合中删除元素的问题

标签 c++ set erase

我在从集合中删除元素时遇到了麻烦。我从以下位置得到 BUILD FAILED:

n2Ar.erase(it);
n3Ar.erase(it);

其中 it 是从 find() 函数接收的指针:例如it = n2Ar.find(*i);

整个程序 list :

#include <stdio.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

#define TESTING_FILE_IN
//#define TESTING_FILE_OUT
//#define DEBUG
//#define SHOW_TIMING

int outputSet(int i) {
    cout << i << endl;
}

/*
 * 
 */
int main() {

    int n1, n2, n3;
    set<int> list, n1Ar, n2Ar, n3Ar;
    set<int>::iterator it;

    scanf("%d", &n1);
    scanf("%d", &n2);
    scanf("%d", &n3);

    int val = 0;

    // Getting lists of voters
    for (unsigned i = 0; i < n1; i++) {
        cin >> val;
        n1Ar.insert(val);
    }

    for (unsigned i = 0; i < n2; i++) {
        cin >> val;
        n2Ar.insert(val);
    }

    for (unsigned i = 0; i < n3; i++) {
        cin >> val;
        n3Ar.insert(val);
    }

    // Processing lists

    for (set<int>::iterator i = n1Ar.begin(); i != n1Ar.end(); ++i) {
        it = n2Ar.find(*i);

        if (it != n2Ar.end()) {
            list.insert(*i);
            n1Ar.erase(i);
            n2Ar.erase(it);

        } else {

            it = n3Ar.find(*i);
            if (it != n3Ar.end()) {
                list.insert(*i);
                n1Ar.erase(i);
                n3Ar.erase(it);
            }
        }
    }

    // Outputting the final list
    cout << list.size() << endl;
    for_each(list.begin(), list.end(), outputSet);

    return 0;
}

我希望你能帮助我理解我在这里做错了什么。我只是从 C++ 开始。

最佳答案

您的代码中有两个问题。

首先,您需要在下面的函数中返回一个值,或者简单地让它返回 void。

// you should return a value here or make it return void
int outputSet(int i)
{
    cout << i << endl;
}

其次,一旦您移除当前迭代器,for 循环的后续迭代中的迭代器将失效。一旦一个元素被移除,它的迭代器i也将失效,以致于后面基于++i的迭代器;

你会得到运行时错误,因为迭代器 i 现在指向你需要以某种方式“重置”它。

MSVC 实现

for (set<int>::iterator i = n1Ar.begin(); i != n1Ar.end(); ++i) {
        it = n2Ar.find(*i);

        if (it != n2Ar.end()) {
            list.insert(*i);
            // the following iterators become invalidated after the
            // current one is removed. You need reset it like
            // i = n1Ar.erase(i);
            n1Ar.erase(i);
            n2Ar.erase(it);

        } else {

            it = n3Ar.find(*i);
            if (it != n3Ar.end()) {
                list.insert(*i);
                // the following iterators become invalidated after the
                // current one is removed. You need reset it like
                // i = n1Ar.erase(i);
                n1Ar.erase(i);
                n3Ar.erase(it);
            }
        }
    }

编辑:请注意,从 set::erase() 返回新的迭代器不是标准方法。这主要是为了性能。

更便携的解决方案

基本思想是在删除当前迭代器之前正确设置下一个迭代器。

   set<int>::iterator i = n1Ar.begin();

   while (i != n1Ar.end())
   {
      it = n2Ar.find(*i);
      if (it != n2Ar.end())
      {
         // the trick is to use "i++" where i is incremented by one while "old" i
         // is removed.
         list.insert(*i);
         n1Ar.erase(i++);
         n2Ar.erase(it);
      }
      else
      {    
         it = n3Ar.find(*i);
         if (it != n3Ar.end())
         {
            list.insert(*i);
            n1Ar.erase(i++);
            n3Ar.erase(it);
         }
         else
         {
            ++i;
         }
      }
   }

关于c++ - 从集合中删除元素的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6967134/

相关文章:

c++ - 堆类的段错误 11

c++ - 警告 : ‘<anonymous>’ is used uninitialized in this function [-Wuninitialized]

c++ - 为集合重载运算符<<

terminal - 清除终端屏幕?

ios - 如何轻轻删除cgcontext中绘制的路径?

c++ - CMake如何处理QtCreator中的对象依赖(.o.d)

c++ - 警告 : section "__textcoal_nt" is deprecate since updating to Mac OSX Sierra

java - java中的高效排列算法

c++ - 如何实现 map 和集合通用的模板?

objective-c - 如何在 iOS 上删除 UIImageView 图像的某些部分?