簡體   English   中英

Flood Fill遞歸堆棧溢出

[英]Flood Fill recursive stack overflow

如果我嘗試填充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;
}

不要使用遞歸。 而是使用堆棧存儲要繪制的坐標。 並迭代直到堆棧為空。

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

出現堆棧溢出的原因是遞歸太深了。

它會走多深? 好吧,使用您設計算法的算法-它實際上將達到深度100*100=10,000

讓我們看一下畫布的填充順序-假設畫布是空的,我們從中間開始填充:

  • 設置中間像素

  • 轉到x,y + 1

  • 做到這一點,直到到達邊緣

  • 在邊緣-移至x-1,0(請記住,我們在頂部)

  • 下去直到底部

等等等

關鍵是-您會越來越深入,直到您填滿畫布,然后在畫布上遍歷一串“遞歸”調用,這很浪費:)

本傑明是可以使用堆棧的,這是正確的,但是堆棧基本上可以做完全相同的事情(只是沒有遞歸),因此堆棧也將達到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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM