如果满足条件,如何消除向量中的元素

时间:2010-03-18 04:57:39

标签: c++

我有一个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中的那些?

6 个答案:

答案 0 :(得分:4)

  1. 您需要增加iter1iter2
  2. erase returns an iterator到下一个元素。删除时,请使用此方法而不是递增迭代器。
  3. 像这样:

    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)

  1. 使用erase可能是一个坏主意,因为它会导致擦除点后出现的所有矩形被复制一个条目。虽然你只需花费O(n ^ 2)时间进行比较,但添加的复制可能会带来很大的开销。我强烈建议您将要保留的recatngles复制到输出vector中。 (如果您希望操作影响输入vector,请先克隆并清除它,然后过滤克隆并将幸存的矩形复制回原始矢量。

  2. 您是否考虑过这样一个事实:通常有很多方法可以删除矩形,使其余的不重叠?你有什么偏好吗?

  3. 假设2的答案是任何最大子集都会这样做(最大子集=子集X使得不在X中的每个矩形与X中的至少一个相交),如果您首先对矩形进行排序,比方说,他们的左下角x坐标(然后可能其次是y坐标),你很有可能减少comaprisons的总数,尽管最坏的情况仍然是O(n ^ 2)。

答案 5 :(得分:0)

向量中元素的顺序是否重要?如果没有,用myRecVec.back()交换你要删除的项目(可能没有操作,但没关系),然后执行pop_back。这不应该使迭代器无效,并且可能比在每次擦除时向前移动元素更好。

如果顺序很重要,你可以使用反向迭代而不是前向迭代(你可以保存项目的迭代器来擦除然后递增反向迭代器)。