迭代二维网格子集的最佳方法

时间:2012-12-11 13:03:29

标签: c++ algorithm iterator iteration

我有一个2d矩形网格,我需要将不同的函数应用于此网格中的节点子集。该子集由矩形边界给出,例如行和列分隔符。由于我不想一遍又一遍地用2 for循环编写迭代代码,我正在考虑两种方法来解决这个问题:

首先创建一个自定义迭代器提供程序,该提供程序使用矩形限制进行初始化,然后在迭代时保留它们。虽然这是可行的,但是使这个迭代器符合要求似乎还有一些工作要做。与标准的aglithithms。

第二种方法是将函数指针传递给遍历for循环的函数,并在内循环中执行它。这也是可行的,但由于我必须传递成员函数,因此可能会创建非常难看的语法。

哪种方式通常更可取?这个用例有没有干净的例子,让我不再重新发明轮子?

注意:由于代码经常执行,因此操作非常重要,

3 个答案:

答案 0 :(得分:1)

为什么不将2d子集数组复制到临时数组,然后将指针传递给数组的开头到不同的函数?

如果将相同的子集多次传递给不同的函数,它应该可以改善缓存未命中率,从而缩短子集迭代所花费的时间。

答案 1 :(得分:1)

从设计的角度来看,我会说迭代器方法更好,因为它在循环体上的复杂性较低(并且可能会比迭代中的复杂性更复杂)。

但我希望通过仿函数方法获得更好的性能。特别是如果您将使用STL样式(带有预期operator()的模板参数)。

答案 2 :(得分:1)

这里值得的是我最终实现的算法。代码不完整,但可能对其他人有用:

//forward declarations
template <typename T> class Grid;
template <typename T> class rectIterator;

//friend forward declarations
template<class T>
bool operator!=(rectIterator<T> const& left, rectIterator<T> const& right);


template<class T>
class rectIterator: public std::iterator<std::forward_iterator_tag, GridTile<T> >{

public:
  typedef GridTile<T> const& const_reference;
  typedef GridTile<T>& reference;
  typedef GridTile<T> const* const_pointer;
  typedef GridTile<T>* pointer;

private:
  Grid<T>* mpGrid;
  int mRow;
  int mCol;
  int mMinRow;
  int mMinCol;
  int mMaxRow;
  int mMaxCol;


public:
  rectIterator(Grid<T>& grid,Rectangle const& rect):
    mpGrid(&grid){
    mpGrid->getRowCol(mpGrid->getTileId(rect.bottomLeft()),mMinRow,mMinCol);
    mpGrid->getRowCol(mpGrid->getTileId(rect.topRight()),mMaxRow,mMaxCol);
    mRow = mMinRow;
    mCol = mMinCol;
  }

  rectIterator():
    mpGrid(0){
    mMinRow= -1;
    mMinCol=-1;
    mMaxRow =-1;
    mMaxCol =-1;
    mCol = 0;
    mRow = 0;
  }

  rectIterator<T>& operator++(){
    if(mCol<=mMaxCol){
      ++mCol;
    }else if(mRow<=mMaxRow){
      ++mRow;
      mCol = mMinCol;
    }else{
      mCol = mpGrid->getCols();
      mRow = mpGrid->getRows();
      mpGrid=0;
    }
    return *this;
  }

  reference operator*() const throw(std::out_of_range, std::runtime_error){
    return mpGrid->at(mRow,mCol);
  }

  pointer operator->() const throw(std::out_of_range, std::runtime_error){
    return &(mpGrid->at(mRow,mCol));
  }

  int row()const{
    return mRow;
  }

  int col()const{
    return mCol;
  }

  friend bool operator!=<>(rectIterator<T> const& left, rectIterator<T> const& right);

};

template<class T>
bool operator!=  (rectIterator<T> const& left, rectIterator<T> const& right){
  return (left.mpGrid != right.mpGrid);
  //DIRTY this is no full compare but fast and sufficient at the moment
}