Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 防止在递归中向向量添加多个相同的项_C++_Recursion - Fatal编程技术网

C++ 防止在递归中向向量添加多个相同的项

C++ 防止在递归中向向量添加多个相同的项,c++,recursion,C++,Recursion,我得到了一种方法,可以将相邻的体素添加到向量中。该方法使用一个包含所有剩余点的向量(也就是说,它们仍然需要被查看,因为它们可能是邻接点),并且如果它们足够接近,可以添加,则查看它们中的每一个。如果一个元素是一个邻居,它也会检查该元素的所有邻接项以添加它们。这是以递归的方式发生的 void remove(std::vector<pcl::PointXYZ> &vec, pcl::PointXYZ p) { for (int i = 0; i < vec.size(

我得到了一种方法,可以将相邻的体素添加到向量中。该方法使用一个包含所有剩余点的向量(也就是说,它们仍然需要被查看,因为它们可能是邻接点),并且如果它们足够接近,可以添加,则查看它们中的每一个。如果一个元素是一个邻居,它也会检查该元素的所有邻接项以添加它们。这是以递归的方式发生的

void remove(std::vector<pcl::PointXYZ> &vec, pcl::PointXYZ p) {
    for (int i = 0; i < vec.size(); i++) {
      if (vec[i].x == p.x && vec[i].y == p.y && vec[i].z == p.z) {
        vec.erase(vec.begin() + i);
        break; // as all points should be unique
      }
    }
}

void addAdjacents(pcl::PointXYZ start, std::vector<pcl::PointXYZ> &newCluster, std::vector<pcl::PointXYZ> &remainingPoints) {
  for (pcl::PointXYZ p : remainingPoints) {
    if (distance(p, start) < 0.015) {
      newCluster.push_back(p);
      remove(remainingPoints, p);
      if (remainingPoints.size() > 0)
        addAdjacents(p, newCluster, remainingPoints);
    }
  }
}
void删除(std::vector&vec,pcl::PointXYZ p){
对于(int i=0;i0)
添加邻接点(p、新簇、剩余点);
}
}
}
问题是,
remainingPoints
-向量中的许多点被多次添加到
newCluster
。我认为这不会发生,但它似乎在内部复制了递归中的向量?如果在更深的一层中删除了一个点,那么外部执行中的for循环仍会以某种方式在该(删除的)元素上迭代

我对C++很陌生,所以我不知道如何防止这个。有人能帮我吗?谢谢

当然,我可以只编写一个方法
addToCluster
,在添加向量之前检查向量是否包含此元素,但我认为可能有一种更优雅的方法首先可以防止这种情况发生

编辑: 据我所知,我在循环中破坏了迭代器。因此,在调用
addadjancets
之后,我需要以某种方式更新迭代器。是这样吗?我可以那样做吗?

这里

list.erase(list.begin() + i);
从名为
list
std::vector
中删除一个元素(实际上并不是向量的最佳名称),该元素会使已删除位置处和之后的迭代器失效。这并不明显,但是当
addadjancets
在同一个容器上迭代时,会发生这种擦除。只留下我们生命中破碎的部分

void addAdjacents(pcl::PointXYZ start, std::vector<pcl::PointXYZ> &newCluster, std::vector<pcl::PointXYZ> &remainingPoints) {
  for (pcl::PointXYZ p : remainingPoints) {
      newCluster.push_back(p);
      //remove(remainingPoints, p); // <- calls erase
      remainingPoints.erase( remainingPoints.begin() + some_index); 
    }
  }
}
void addadjancets(pcl::PointXYZ start,std::vector&newCluster,std::vector&remainingPoints){
对于(pcl::PointXYZ p:剩余点){
newCluster.push_back(p);

//删除(remainingPoints,p);//您需要将要迁移的点与从输入中删除的点分开标识

template<typename BidirIt>
BidirIt addAdjacentsImpl(pcl::PointXYZ start, std::vector<pcl::PointXYZ> &newCluster, BidirIt first, BidirIt last) {
    auto part = std::stable_partition(first, last, [&](auto p){ return distance(p, start) >= 0.015; });
    for (auto it = part; it != last; ++it) {
        newCluster.push_back(*it);
        part = addAdjacentsImpl(*it, newCluster, first, part);
    }
    return part;
}
模板
BidirIt addadjacentsiml(pcl::PointXYZ start,std::vector&newCluster,BidirIt first,BidirIt last){
autopart=std::stable_分区(第一,最后,[&](autop){返回距离(p,开始)>=0.015;});
for(自动it=零件;it!=最后一个;++it){
newCluster.push_back(*it);
part=addadjacentsiml(*it,newCluster,first,part);
}
返回部分;
}
这只是对元素进行重新排序,以便我们希望删除的元素位于我们希望保留的元素之后。我将其作为模板编写,因为我不想命名特定的迭代器类型

void addAdjacents(pcl::PointXYZ start, std::vector<pcl::PointXYZ> &newCluster, std::vector<pcl::PointXYZ> &remainingPoints) {
    auto last = addAdjacentsImpl(start, newCluster, remainingPoints.begin(), remainingPoints.end());
    remainingPoints.erase(last, remainingPoints.end());
}
void addadjancets(pcl::PointXYZ start,std::vector&newCluster,std::vector&remainingPoints){
auto last=addadjacentsiml(start、newCluster、remainingPoints.begin()、remainingPoints.end());
remainingPoints.erase(最后,remainingPoints.end());
}

您的代码缺少定义,请参阅尝试通过值而不是引用传递向量。在您的代码中,您传递的是引用,因此所有函数调用共享同一个对象。只需删除函数原型中的
&
,然后重试。如何(例如)
remove
implemented?我们无法在不知道实现外观的情况下帮助您实现。乍一看,在迭代过程中更改向量可能不是最好的主意(取决于实现外观)。当您在迭代过程中从容器中删除元素时,您必须考虑删除的元素。为什么要命名
std::vector
列表?这很糟糕……是的。我认为这正是我的问题。但我不确定如何解决此问题。@Hawky如果您查看
std::vector
的列,您可以在引用nd迭代器在有条件地擦除后有效,条件是迭代器在被擦除的迭代器之前,因此不能保证在被擦除之后迭代器有效erase@formerlyknownas_463035818看看我在主帖下的评论,我说的是
std::list
,因为名字是
list
,所以我错了e、 @Hawky yes看到了。我留下了评论,以防误会再次发生。这是一个很好的解决办法。谢谢!