我有一个Rect:vector<Rect> myRecVec;
我想删除向量中重叠的那些:
所以我有这样的2个嵌套循环:
vector<Rect>::iterator iter1 = myRecVec.begin();
vector<Rect>::iterator iter2 = myRecVec.begin();
while( iter1 != myRecVec.end() ) {
Rectangle r1 = *iter1;
while( iter2 != myRecVec.end() ) {
Rectangle r2 = *iter1;
if (r1 != r2) {
if (r1.intersects(r2)) {
// remove r2 from myRectVec
}
}
}
}
我的问题是如何在不拧紧我的迭代器的情况下从myRectVect中删除r2?既然我正在迭代一个向量并同时修改向量? 我已经考虑过将r2放在temp rectVect中,然后稍后(在迭代后)从rectVect中删除它们。但是如何在迭代期间跳过这个临时rectVect中的那些?
答案 0 :(得分:4)
iter1
和iter2
。erase
returns an iterator到下一个元素。删除时,请使用此方法而不是递增迭代器。像这样:
while( iter1 != myRecVec.end() ) {
Rectangle r1 = *iter1;
iter2 = iter1 + 1;
while( iter2 != myRecVec.end() ) {
Rectangle r2 = *iter2;
if( r1.intersects(r2) ) {
iter2 = myRectVec.erase(iter2);
}
else {
++iter2;
}
++iter1;
}
答案 1 :(得分:1)
首先,你可能只想从iter1运行iter2到结束,因为r1.intersects(r2)iff r2.intersects(r1)。完成此调整后,您所要做的就是在擦除它的同一周期内不增加r2。你可以这样做,因为擦除保证的元素不会导致std :: vector重新分配内存。
答案 2 :(得分:0)
另一种技术是从最后开始并迭代到前面,然后当前迭代器是有效的,而begin()当然永远不会改变。
由于移动的元素较少,因此效率也更高。
如果要删除大量项目,可能会更快(更容易)将未删除的项目复制到新的矢量然后替换原始项目。
最后,如果可以对元素进行排序,则可以使用set_intersects查找相交的向量范围。
答案 3 :(得分:0)
使用vector :: erase将擦除元素后的元素返回给元素。您可以使用此迭代器来保持循环(在针对.end()进行检查之后)。不要使用任何其他迭代器,因为它可能已失效。
答案 4 :(得分:0)
使用erase
可能是一个坏主意,因为它会导致擦除点后出现的所有矩形被复制一个条目。虽然你只需花费O(n ^ 2)时间进行比较,但添加的复制可能会带来很大的开销。我强烈建议您将要保留的recatngles复制到输出vector
中。 (如果您希望操作影响输入vector
,请先克隆并清除它,然后过滤克隆并将幸存的矩形复制回原始矢量。
您是否考虑过这样一个事实:通常有很多方法可以删除矩形,使其余的不重叠?你有什么偏好吗?
假设2的答案是任何最大子集都会这样做(最大子集=子集X使得不在X中的每个矩形与X中的至少一个相交),如果您首先对矩形进行排序,比方说,他们的左下角x坐标(然后可能其次是y坐标),你很有可能减少comaprisons的总数,尽管最坏的情况仍然是O(n ^ 2)。
答案 5 :(得分:0)
向量中元素的顺序是否重要?如果没有,用myRecVec.back()交换你要删除的项目(可能没有操作,但没关系),然后执行pop_back。这不应该使迭代器无效,并且可能比在每次擦除时向前移动元素更好。
如果顺序很重要,你可以使用反向迭代而不是前向迭代(你可以保存项目的迭代器来擦除然后递增反向迭代器)。