Flood Fill递归堆栈溢出

时间:2015-06-02 23:48:01

标签: c++ recursion stack stack-overflow fill

如果我尝试填充100x100矩形,那么我会溢出。 50x50工作正常。

有没有办法解决溢出问题?

我还打印出堆栈编号,有时工作矩形堆栈高于大堆积(它在7000左右崩溃)。

void draw(int x, int y)
{
if ((x >= 0 && x < 100) && (y >= 0 && y < 100))
    {
            canvas.set_pixel(x, y);
            if (!canvas.get_pixel(x, y + 1))draw(x, y + 1);
            if (!canvas.get_pixel(x, y-1))draw(x, y - 1);
            if (!canvas.get_pixel(x - 1, y))draw(x - 1, y);
            if (!canvas.get_pixel(x+1, y))draw(x + 1, y);   

    }

    return;
}

2 个答案:

答案 0 :(得分:2)

不要使用递归。而是使用堆栈来存储您想要绘制的坐标。并迭代直到堆栈为空。

void draw(int x, int y)
{
    struct coordinate { int x, y; };
    std::stack<coordinate> to_draw;
    to_draw.push({x, y});

    while (!to_draw.empty())
    {
        auto top = to_draw.top();
        to_draw.pop();
        if (  (top.x >= 0 && top.x < 100)
           && (top.y >= 0 && top.y < 100)
           && !canvas.get_pixel(top.x, top.y))
        {
            canvas.set_pixel(top.x, top.y);
            to_draw.push({top.x, top.y + 1});
            to_draw.push({top.x, top.y - 1});
            to_draw.push({top.x + 1, top.y});
            to_draw.push({top.x - 1, top.y});
        }            
    }
}

答案 1 :(得分:2)

你得到堆栈溢出的原因是递归太深了。

它有多深?好吧,使用算法设计它的方式 - 它实际上会深入100*100=10,000

让我们看一下画布的填充顺序 - 假设画布为空,我们从中间开始填充:

  • 设置中间像素

  • 转到x,y + 1

  • 这样做直到你到达边缘

  • 在边缘 - 移动到x-1,0(记住,我们在顶部)

  • 直到底部

等。等

关键是 - 你要越来越深,直到你填满画布,然后在画布周围有一个递归调用的“链”,这是浪费:)

Benjamin是对的,你可以使用堆栈,但堆栈基本上完全相同(只是没有递归),所以堆栈也将达到10,000深度。仍然是一种浪费,在某些情况下你会耗尽内存(对于位图画布,每个像素需要1位,但是对于x,y,每个像素的堆栈将有2个整数,因此可能需要64倍的内存。画布)

相反 - 使用队列!几乎相同的代码:

void draw(int x, int y)
{
    struct coordinate { int x, y; };
    std::queue<coordinate> to_draw; // <- changed from stack to queue
    to_draw.push({x, y});

    while (!to_draw.empty())
    {
        auto top = to_draw.front(); // <- changed from top to front
        to_draw.pop();
        if (  (top.x >= 0 && top.x < 100)
           && (top.y >= 0 && top.y < 100)
           && !canvas.get_pixel(top.x, top.y))
        {
            canvas.set_pixel(top.x, top.y);
            to_draw.push({top.x, top.y + 1});
            to_draw.push({top.x, top.y - 1});
            to_draw.push({top.x + 1, top.y});
            to_draw.push({top.x - 1, top.y});
        }            
    }
}

现在所需的内存将是<=4*100!换句话说 - 通过从堆栈更改为队列,我们​​将所需的内存从N*N更改为4*N