If i try to Fill a 100x100 rectangle then i get an overflow. A 50x50 works fine.
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).
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
!
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
do that until you get to the edge
at the edge - move to x-1,0 (remember, we're at the top)
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. 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)
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
! In other words - by changing from stack to queue we changed the memory needed from N*N
to 4*N
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.