简体   繁体   English

Flood Fill递归堆栈溢出

[英]Flood Fill recursive stack overflow

If i try to Fill a 100x100 rectangle then i get an overflow. 如果我尝试填充100x100矩形,则会溢出。 A 50x50 works fine. 50x50可以正常工作。

Is there a way to fix the overflow? 有办法解决溢出问题吗?

I also print out the Stack Number and sometimes the working rectangle Stack is higher then the big one (it crashes around 7000). 我还会打印出堆栈编号,有时工作矩形堆栈要比大矩形堆栈高(它崩溃了大约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;
}

Don't use recursion. 不要使用递归。 Instead, use a stack to store the coordinates you want to draw. 而是使用堆栈存储要绘制的坐标。 And iterate until the stack is empty. 并迭代直到堆栈为空。

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});
        }            
    }
}

The reason you get a stack overflow is that the recursion goes too deep. 出现堆栈溢出的原因是递归太深了。

How deep will it go? 它会走多深? Well, with the algorithm the way you designed it - it will actually go to depth 100*100=10,000 ! 好吧,使用您设计算法的算法-它实际上将达到深度100*100=10,000

Let's look at in what order will the canvas be filled - assuming the canvas is empty and we start filling from the middle: 让我们看一下画布的填充顺序-假设画布是空的,我们从中间开始填充:

  • set the middle pixel 设置中间像素

  • go to x,y+1 转到x,y + 1

  • do that until you get to the edge 做到这一点,直到到达边缘

  • at the edge - move to x-1,0 (remember, we're at the top) 在边缘-移至x-1,0(请记住,我们在顶部)

  • go down until the bottom 下去直到底部

etc. etc. 等等等

The point is - you're going deeper and deeper until you fill the canvas, and then have a "chain" of recursion calls going all around the canvas and it's a waste :) 关键是-您会越来越深入,直到您填满画布,然后在画布上遍历一串“递归”调用,这很浪费:)

Benjamin is right that you can use a stack, but a stack basically does the exact same thing (just without the recursion), so the stack will get to depth 10,000 as well. 本杰明是可以使用堆栈的,这是正确的,但是堆栈基本上可以做完全相同的事情(只是没有递归),因此堆栈也将达到10,000的深度。 Still a waste, and you run out of memory in some cases (for a bitmap canvas, each pixel takes 1 bit, but the stack will have 2 integers per pixel for x,y , and thus could take 64 times more memory than the canvas) 仍然是浪费,在某些情况下会耗尽内存(对于位图画布,每个像素占用1位,但是对于x,y ,堆栈将每个像素具有2个整数,因此可能比画布占用64倍的内存)

Instead - use a queue! 相反-使用队列! Almost the same code: 几乎相同的代码:

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});
        }            
    }
}

And now the memory needed will be <=4*100 ! 现在所需的内存将是<=4*100 In other words - by changing from stack to queue we changed the memory needed from N*N to 4*N . 换句话说-通过从堆栈更改为队列,我们​​将所需的内存从N*N更改为4*N

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM