C++ 递归优化

C++ 递归优化,c++,recursion,C++,Recursion,我目前正在研究一种算法,在某个时刻,我必须浏览一幅图像,并对具有相同属性的像素进行分组。我从最左上方的像素开始,使用递归:从输入像素我可以得到相邻像素的高度,如果第一个像素具有相同的属性,那么我通过将该像素作为输入像素传递来调用相同的函数 下面是一些代码(请记住,这仍在进行中)。 基本调用者: // R.A.G. for( std::vector<Cell*>::iterator iterCell = cellVec.begin(); iterCell != cellVec

我目前正在研究一种算法,在某个时刻,我必须浏览一幅图像,并对具有相同属性的像素进行分组。我从最左上方的像素开始,使用递归:从输入像素我可以得到相邻像素的高度,如果第一个像素具有相同的属性,那么我通过将该像素作为输入像素传递来调用相同的函数

下面是一些代码(请记住,这仍在进行中)。 基本调用者:

// R.A.G.
for( std::vector<Cell*>::iterator iterCell = cellVec.begin();
     iterCell != cellVec.end(); ++iterCell )
{
    Cell* mother = (*iterCell);

    if( mother->visited != true )
    {
        mother->visited = true;
    }
    CheckNeighbors( mother );
}
如何检查单元格:

Cell*
CheckCell( int x, int y, Cell* cell )
{
    // Here a cell is one pixel, but it depends on the size of the window we choose.
    // So for an image of 640*480, windowSize = 1, w = 640, h = 480
    x += cell->window.x()/windowSize;
    y += cell->window.y()/windowSize;

    // The cell at (x, y) coordinates is not in the map
    if( x < 0 || x >= w || y < 0 || y >= h ) return cell;

    // Get the neighbor cell in (x, y)
    // NB: cellVec has been filled up earlier and contains all the cells
    Cell* neighbor = cellVec.at( (y*w) + x );

    // The neighbor cell has already been visited
    if( neighbor->visited ) return cell;

    // The neighbor cell is of the same class as the mother cell
    if( neighbor->cClass != cell->cClass ) return cell;

    // Set the region number for the neighbor
    neighbor->visited = true;

    return neighbor;
}
单元*
检查单元格(整数x,整数y,单元格*单元格)
{
//这里一个单元是一个像素,但它取决于我们选择的窗口大小。
//所以对于640*480的图像,windowSize=1,w=640,h=480
x+=单元格->窗口.x()/WindowsSize;
y+=单元格->窗口.y()/WindowsSize;
//(x,y)坐标处的单元格不在地图中
如果(x<0 | | x>=w | | y<0 | | y>=h)返回单元;
//获取(x,y)中的相邻单元
//注意:cellVec已提前填充,包含所有单元格
Cell*neighbor=cellVec.at((y*w)+x);
//邻居的手机已经被访问过了
如果(邻居->访问)返回单元格;
//相邻单元与母单元属于同一类别
如果(邻居->类别!=单元格->类别)返回单元格;
//设置邻居的区域编号
邻居->访问=真;
返回邻居;
}
所以我的问题是:我确信这是可以改进的,但我想知道如何改进。 我应该使用其他递归吗? 如何改进这种递归? 我读过关于尾部调用优化的文章,但是在我的例子中,我不能放弃调用方的状态,所以这不能应用。但是,我还有别的窍门吗

谢谢你的回答,我希望我已经说得够清楚了


注意:如果我有一个单色图像,大小为640*480,单元格大小为2*2像素,我有153765个呼叫。当然还有一个1*1单元格大小的segfault。我知道我可以增加堆栈的大小,但我更愿意找到另一种解决方案。

使用迭代方法会快得多,因为你可以读取向量中的所有元素,并且可以线性地运行它。这对缓存更加友好,并且您可以消除所有的抵消内容

// Copy all elements starting from the selected cell pointed to by the iterator, if 
// they are equal to the cell
void checkAllCells(vector<Cell*> input, vector<Cell*>::iterator it; vector<Cell*> output)
{
    auto localIt = it;
    while( localIt != input.end())
    {
        if ((*localIt)->class == (*it)->class)
        {
            output.pushback(*it);
        }
    }
}
//如果需要,从迭代器指向的选定单元格开始复制所有元素
//它们与细胞相等
void checkAllCells(向量输入,向量::迭代器it;向量输出)
{
自动本地化=it;
while(localIt!=input.end())
{
if((*localIt)->class==(*it)->class)
{
输出。回推(*it);
}
}
}
请注意,您不需要像
visted
等那样记账。因为从第一个元素开始,您会发现所有其他元素都是相等的。如果你接着考虑第二个元素,你知道,你已经考虑了前一个元素,你正在做的是,实现为

要改进它,您可以:

  • 将其重新编码为
  • 使用堆栈实现深度优先搜索。这仍然是相同的想法,但是使用堆栈而不是递归应该使代码更快,使用更少的内存

递归有多深?哈哈,这是个好问题,我忘了。问题是,如果我有一个单色图像,大小为640*480,单元大小为2*2像素,那么我有153765个调用。当然还有一个1*1单元格大小的segfault。我知道我可以增加堆栈的大小,但我更愿意找到另一种解决方案。递归通常需要。为了减少深度,你需要。”我读了这篇关于尾部调用优化的文章……但在我的案例“你在谈论哪些状态?”中,我不能丢弃调用方的状态,尾部调用递归与迭代循环几乎相同。你不应该依赖尾部递归来避免堆栈溢出(LOL)嗨,问题是我不希望同一类的所有单元格都在同一个容器中。我希望同一类的所有单元格在同一容器中相邻!一个像素可以是同一类但不是相邻的,这意味着它不在同一个容器中…然后你应该在图片中运行一个过滤器,这是一个二维的单元数组。该算法与上面的算法类似,但同样,由于它是迭代的,并且在内存中是线性的,所以速度会快得多。我会试着为它写一些代码…看:这只会找到下一个邻居。如果你想找到所有相邻的元素,BFS方法可能是最容易实现的。谢谢你的代码,我正在看一看。我想我可能会支持n.m和@MAK指出的BFS方法。感谢您的评论,我将把它重新编码为BFS以检查性能。
// Copy all elements starting from the selected cell pointed to by the iterator, if 
// they are equal to the cell
void checkAllCells(vector<Cell*> input, vector<Cell*>::iterator it; vector<Cell*> output)
{
    auto localIt = it;
    while( localIt != input.end())
    {
        if ((*localIt)->class == (*it)->class)
        {
            output.pushback(*it);
        }
    }
}