[英]Deleting like elements in two vectors C++
我正在尝试搜索两个向量(每个大小)以查找相同的元素,然后删除这两个元素。
我的实现如下:
for (int i = vec1.size() - 1; i >= 0; i--) {
for (int j = 0; j < vec2.size(); j++) {
if (vec1[i] == vec2[j]) {
vec1.erase(vec1.begin() + i);
vec2.erase(vec2.begin() + j);
}
}
}
但是,尽管这在大多数情况下都可行,但我遇到了一些不可行的地方。 是通过这些向量进行迭代的方式,还是只是将这一切弄错了?
问题是,从vec1
和vec2
删除元素后,当您遍历vec2
,您将继续访问vec1[i]
。 如果您在删除vec1
的最后一个元素之后执行此操作,则会导致未定义的行为,因为vec1[i]
不再有效。 if
要解决此问题,请在您的语句中添加break
语句。
for (int i = vec1.size() - 1; i >= 0; i--) {
for (int j = 0; j < vec2.size(); j++) {
if (vec1[i] == vec2[j]) {
vec1.erase(vec1.begin() + i);
vec2.erase(vec2.begin() + j);
break; // Look at next element in vec1
}
}
}
还有一种更有效的方法( O(n*log(n)+m*log(m)+n+m)
代替O(n*m)
来实现n=vec1.size()
和m=vec2.size()
)。 它涉及对向量进行排序。 我留给你找出答案。
实际上,您根本不需要向后迭代。 在这种情况下,您的代码可以是:
for (int i = 0; i < vec1.size(); i++) {
for (int j = 0; j < vec2.size(); j++) {
if (vec1[i] == vec2[j]) {
vec1.erase(vec1.begin() + i);
vec2.erase(vec2.begin() + j);
}
}
}
但是,请稍等...删除元素后会发生什么? 然后,其索引之后的所有元素都减小1,因此我们将跳过下一项! 要解决此问题,我们可以添加此小修改:
vec1.erase(vec1.begin() + i--);
vec2.erase(vec2.begin() + j--);
^^^^
即使我们通过擦除来更改大小,这也将起作用,因为我们正在每个循环中检查vec2
的大小! 但是,如果我们最终删除了vec1
的最后一项, vec1
怎么vec1
? 我们,直到我们反复一路过关斩将不要再比较其尺寸vec2
,这将是你的一个问题vec1 = {2}, vec2 = {2, 2, 2}
例子。 为了解决这个问题,我们可以突破内部循环并重复对vec2
进行检查。
将它们放在一起(并将您的下标运算符更改为.at()
调用,以便我们进行边界检查),您将获得:
for (int i = 0; i < vec1.size(); i++) {
for (int j = 0; j < vec2.size(); j++) {
if (vec1.at(i) == vec2.at(j)) {
vec1.erase(vec1.begin() + i--);
vec2.erase(vec2.begin() + j--);
break;
}
}
}
(在此处查看实际操作: ideone )
如果可以排序,则可以执行以下操作:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> ex {3, 1, 2, 3, 3, 4, 5}, as {2, 3, 6, 1, 1, 1}, tmp;
std::sort(std::begin(ex), std::end(ex));
std::sort(std::begin(as), std::end(as));
as.erase(
std::remove_if(
std::begin(as),std::end(as),
[&](int const& s){
bool found = std::binary_search(std::begin(ex), std::end(ex), s);
if (found) {
tmp.push_back(s);
}
return found;}), std::end(as));
for (auto const& i : tmp) {
ex.erase(std::remove(std::begin(ex),std::end(ex), i), std::end(ex));
}
}
尝试使用std::set_difference
从另一个向量中减去一个向量,然后在std::merge
的帮助下将这些减法std::merge
。 但是必须对向量进行排序才能使用这些功能,因此请首先使用std::sort
。 代码在这里:
void TraceVector( std::vector<int> v, const std::string& title )
{
if ( !title.empty() )
{
std::cout << title << std::endl;
}
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
int main() {
std::vector<int> Vec1 {7, 1, 2, 5, 5, 5, 8, 9};
std::vector<int> Vec2 {3, 2, 5, 7, 10};
std::vector<int> Difference1; // Contains subtraction Vec1 - Vec2
std::vector<int> Difference2;// Contains subtraction Vec2 - Vec1
std::vector<int> Merged; // RESULT Merged vector after subtractions
//Need to be sorted
std::sort(Vec1.begin(), Vec1.end());
std::sort(Vec2.begin(), Vec2.end());
TraceVector(Vec1, "Vec1 sorted is: ");
TraceVector(Vec2, "Vec2 sorted is: ");
//Make subtractions
std::set_difference(Vec1.begin(), Vec1.end(), Vec2.begin(), Vec2.end(),
std::inserter(Difference1, Difference1.begin()));
std::set_difference(Vec2.begin(), Vec2.end(), Vec1.begin(), Vec1.end(),
std::inserter(Difference2, Difference2.begin()));
TraceVector(Difference1, "Difference is: ");
TraceVector(Difference2, "Difference is: ");
//Merge subtrctions
std::merge(Difference1.begin(), Difference1.end(), Difference2.begin(), Difference2.end(), back_inserter(Merged));
TraceVector(Merged, "Merged is: ");
}
输出为:
Vec1 sorted is:
1,2,5,5,5,7,8,9,
Vec2 sorted is:
2,3,5,7,10,
Difference is:
1,5,5,8,9,
Difference is:
3,10,
Merged is:
1,3,5,5,8,9,10,
Program ended with exit code: 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.