从vector中删除元素

我想使用擦除方法从vector中清除元素。 但是这里的问题是元素不能保证在向量中只出现一次。 它可能会出现多次,我需要清除所有这些。 我的代码是这样的:

void erase(std::vector<int>& myNumbers_in, int number_in) { std::vector<int>::iterator iter = myNumbers_in.begin(); std::vector<int>::iterator endIter = myNumbers_in.end(); for(; iter != endIter; ++iter) { if(*iter == number_in) { myNumbers_in.erase(iter); } } } int main(int argc, char* argv[]) { std::vector<int> myNmbers; for(int i = 0; i < 2; ++i) { myNmbers.push_back(i); myNmbers.push_back(i); } erase(myNmbers, 1); return 0; } 

这段代码显然崩溃了,因为我在遍历它的时候改变了向量的结尾。 达到这个目标的最好方法是什么? 也就是说有没有办法做到这一点,而无需多次遍历向量或创build一个向量副本?

使用删除/删除成语 :

 std::vector<int>& vec = myNumbers; // use shorter name vec.erase(std::remove(vec.begin(), vec.end(), number_in), vec.end()); 

会发生什么是remove压缩的元素不同于要删除的值( number_in )在vector的开始,并将迭代器返回到该范围之后的第一个元素。 然后erase删除这些元素(谁的价值是未指定的)。

调用擦除将使迭代器失效,您可以使用:

 void erase(std::vector<int>& myNumbers_in, int number_in) { std::vector<int>::iterator iter = myNumbers_in.begin(); while (iter != myNumbers_in.end()) { if (*iter == number_in) { iter = myNumbers_in.erase(iter); } else { ++iter; } } } 

或者你可以使用std :: remove_if一个函数和std :: vector :: erase:

 struct Eraser { Eraser(int number_in) : number_in(number_in) {} int number_in; bool operator()(int i) const { return i == number_in; } }; std::vector<int> myNumbers; myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), Eraser(number_in)), myNumbers.end()); 

在这种情况下,你可以使用std :: remove来代替自己的函子:

 std::vector<int> myNumbers; myNumbers.erase(std::remove(myNumbers.begin(), myNumbers.end(), number_in), myNumbers.end()); 
  1. 你可以迭代使用索引访问,

  2. 为了避免O(n ^ 2)复杂性,可以使用两个索引:i – 当前testing索引,j – 索引来存储下一个项目,并在循环结束时新增大小的向量。

码:

 void erase(std::vector<int>& v, int num) { size_t j = 0; for (size_t i = 0; i < v.size(); ++i) { if (v[i] != num) v[j++] = v[i]; } // trim vector to new size v.resize(j); } 

在这种情况下,你没有使迭代器失效,复杂度是O(n),代码非常简洁,你不需要编写一些助手类,虽然在某些情况下使用助手类可以在更灵活的代码中受益。

此代码不使用erase方法,但可以解决您的任务。

使用纯粹的stl,你可以通过以下方式来做到这一点(这与Motti的答案类似):

 #include <algorithm> void erase(std::vector<int>& v, int num) { vector<int>::iterator it = remove(v.begin(), v.end(), num); v.erase(it, v.end()); } 

根据你为什么这样做,使用std :: set可能比std :: vector更好。

它允许每个元素只发生一次。 如果多次添加,则只会有一个实例被删除。 这将使擦除操作变得微不足道。 擦除操作的时间复杂度也比vector时间复杂度要低,但是增加元素的速度比较慢,所以可能没有多大的优势。

这当然不会工作,如果你有兴趣多less次元素已被添加到您的向量或添加元素的顺序。

您可以从结尾开始,或者在元素被擦除时更新结束。

它看起来像这样:

 void erase(std::vector<int>& myNumbers_in, int number_in) { std::vector<int>::iterator iter = myNumbers_in.begin(); std::vector<int>::iterator endIter = myNumbers_in.end(); for(; iter != endIter; ++iter) { if(*iter == number_in) { myNumbers_in.erase(iter); endIter = myNumbers_in.end(); } } }