【问题标题】:Fill color before or after recursive call (Flood Fill algorithm)在递归调用之前或之后填充颜色(Flood Fill 算法)
【发布时间】:2021-10-06 12:23:51
【问题描述】:

当我遇到这个疑问时,我正在实现一个基本版本的洪水填充算法。

你应该在递归调用之前还是递归调用之后为当前单元格着色(即image[sr][sc] = newColor)?为什么这两种方法有区别?当当前单元格在递归调用起作用之前着色但如果我更改顺序则会给出分段错误。

代码如下:

vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
    if(image.size()<=0 || image[sr][sc] == newColor) return image;
    int rows = image.size(),cols=image[sr].size();
    int temp = image[sr][sc];
    image[sr][sc] = newColor;
    //check up
    if((sr-1)>=0 && image[sr-1][sc] == temp){
        image = floodFill(image,sr-1,sc,newColor);
    }
    //check left
    if((sc-1)>=0 && image[sr][sc-1] == temp){
        image = floodFill(image,sr,sc-1,newColor);
    }
    //check right
    if((sc+1)<cols && image[sr][sc+1] == temp){
        image = floodFill(image,sr,sc+1,newColor);
    }
    //check down
    if((sr+1)<rows && image[sr+1][sc] == temp){
        image = floodFill(image,sr+1,sc,newColor);
    }
    //if i put the image[sr][sc] = newColor; here it give seg error
    return image;
}

【问题讨论】:

  • 显然你应该先上色,因为后上色不起作用,你可以清楚地看到。又是什么问题?
  • 下班后为什么不上色?就在返回调用函数之前,我可以着色并返回对吗?(我还是新手,也许我没有看到明显的东西?)
  • 最好自己弄清楚为什么着色后不起作用。启动调试器并在 1x2 矩阵上逐步运行它。

标签: c++ algorithm recursion segmentation-fault


【解决方案1】:

此代码似乎通过引用就地修改了image,因此无需返回它——事实上,这样做是个坏主意。在递归调用之后将单元格写入新颜色将不起作用,因为子调用的 image[sr+N][sc] == tempimage[sr][sc] == newColor 的基本案例相关测试将是错误的 - 父调用计划为单元格着色,但因为它有'没有解决它,它被重新访问,当它产生更多子调用时给出一个无限循环。

这是我在一个可运行示例中的建议,您可以根据自己的用例进行调整:

#include <iostream>
#include <vector>

void floodFill(
    std::vector <std::vector<int> > &image,
    int r,
    int c,
    int newColor,
    int oldColor
) {
    if (
        r < 0 ||
        c < 0 ||
        r >= (int)image.size() ||
        c >= (int)image[r].size() ||
        image[r][c] == newColor ||
        image[r][c] != oldColor
    ) {
        return;
    }

    image[r][c] = newColor;
    floodFill(image, r - 1, c, newColor, oldColor);
    floodFill(image, r, c - 1, newColor, oldColor);
    floodFill(image, r, c + 1, newColor, oldColor);
    floodFill(image, r + 1, c, newColor, oldColor);
}

void printMatrix(std::vector<std::vector<int> > &img) {
    for (auto row : img) {
        for (int cell : row) {
            std::cout << cell << " ";
        }

        std::cout << "\n";
    }
}

int main() {
    std::vector<std::vector<int> > img{
        {0, 2, 2, 1, 1, 1,},
        {0, 0, 0, 1, 0, 1,},
        {1, 1, 0, 1, 0, 1,},
        {0, 1, 0, 1, 1, 1,},
        {1, 0, 0, 0, 0, 0,},
        {0, 0, 0, 2, 1, 0,},
    };
    printMatrix(img);
    std::cout << "\n";
    floodFill(img, 2, 2, 1, img[2][2]);
    printMatrix(img);
    return 0;
}

输出:

0 2 2 1 1 1
0 0 0 1 0 1
1 1 0 1 0 1
0 1 0 1 1 1
1 0 0 0 0 0
0 0 0 2 1 0

1 2 2 1 1 1
1 1 1 1 0 1
1 1 1 1 0 1
0 1 1 1 1 1
1 1 1 1 1 1
1 1 1 2 1 1

如您所见,您可以通过在递归调用开始时进行一次基本情况检查来消除大量重复。这增加了一个与检查分支条件相关的额外调用,但这可能是一个过早的优化。

【讨论】:

  • 是的,非常感谢我得到了我之前没看到的东西,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2014-02-16
相关资源
最近更新 更多