【问题标题】:How to handle recursion?如何处理递归?
【发布时间】:2014-05-23 10:16:53
【问题描述】:

一个二维数组代表一张图片,每个像素都有一种颜色,这个递归函数的工作就是将周围像素(x,y)的一个相同颜色(c)的区域转换成新的颜色(newC)。函数是工作正常,直到我通过像 x=200, y=200 这样的大数字并发生 SO。 我该如何处理这种情况?或者是否有比递归更好的解决方案?

void Region(int x, int y, char newC, char c) { //c is current color, newC is new Color
    if(c == newC) return;
    arr[y][x]=newC;
    if(arr[y][x-1 ]== c && x-1 > 0) Region(x-1, y, newC, c);
    if(arr[y-1][x] == c && y-1 > 0) Region(x, y-1, newC, c);
    if(arr[y][x+1] == c && x+1 <= M) Region(x+1, y, newC, c);
    if(arr[y+1][x] == c && y+1 <= N) Region(x, y+1, newC, c);
}

2 个区域(Os 和 Vs)的示例:

呜呜呜
呜呜呜
OVVVOO
OVVOOO
呜呜呜

【问题讨论】:

  • 听起来您在谈论flood fill,在这种情况下,最好使用链接中描述的基于堆栈的递归。
  • @RogerRowland 谢谢这个链接很有帮助!如果有人告诉我代码有什么问题,我将不胜感激:void Region(int x,int y,char newC,char c) { char n; if(c==newC)return; myqueue.empty(); myqueue.push_back(arr[y][x]); while (myqueue.size()!=0) { n=myqueue.back(); myqueue.pop_back(); if(n==c) { n=newC; if(x-1&gt;0)myqueue.push_back(arr[y][x-1]); if(y-1&gt;0)myqueue.push_back(arr[y-1][x]); if(x+1&lt;=M)myqueue.push_back(arr[y][x+1]); if(y+1&lt;=N)myqueue.push_back(arr[y+1][x]); } } }

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


【解决方案1】:

既然您将整个事物更改为一种颜色,为什么不只使用 2 个嵌套的 for 循环,那么您就不必进行 if 语句检查,因此您的函数不会是递归的。

试试这个:

for(int i = 0; i < y; i++){
  for(int j = 0; j < x; j++){
      arr[i][j] = newC;
  }
}

【讨论】:

  • 不是整个事情,我的意思是区域:要填充的区域 R 定义如下。像素 (X,Y) 属于该区域。另一个像素属于区域 R 当且仅当它与像素 (X,Y) 具有相同的颜色并且与属于该区域的任何像素具有公共边。无论如何谢谢:)
  • 所以你想改变 Y 数量的 X 像素的颜色?我认为嵌套循环仍然适用于您只需正确设置 y 和 x 的区域,剩下的事情他们会做。
  • 我不完全明白您要更改哪些像素,也许您可​​以展示一个区域如何从一种颜色变为另一种颜色?
  • OOOOOO OOVOOO OVVVOO OVVOOO OVOOOO 这里我有 2 个区域 Vs 区域和 Os 区域每个字符串之间有一个断线
  • 泛洪填充会更改指定的元素及其旁边具有相同值的任何元素,因此在问题的示例中,如果您选择了 2,2,那么所有的 V 都将更改为新的价值。但是,如果右下角有一个 V,它就不会改变,因为它没有连接到洪水填充的起点。您当前的答案根本没有解决问题。
【解决方案2】:

在链接中,有一个比递归更有效的解决方案

http://en.wikipedia.org/wiki/Flood_fill

Flood-fill(节点、目标颜色、替换颜色):

1. If target-color is equal to replacement-color, return.
2. Set Q to the empty queue.
3. Add node to the end of Q.
4. While Q is not empty: 
5.     Set n equal to the last element of Q.
6.     Remove last element from Q.
7.     If the color of n is equal to target-color:
8.         Set the color of n to replacement-color.
9.         Add west node to end of Q.
10.        Add east node to end of Q.
11.        Add north node to end of Q.
12.        Add south node to end of Q.
13. Return.

这是我第一次尝试将伪代码转换为 C++:

std::deque<char> myqueue;
void Region(int x,int y,char newC,char c)
{
    char n;
    if(c==newC)return;
    myqueue.empty();
    myqueue.push_back(arr[y][x]);
    while (myqueue.size()!=0)
    {
        n=myqueue.back();
        myqueue.pop_back();
        if(n==c)
        {
            n=newC;
            if(x-1>0)    myqueue.push_back(arr[y][x-1]);
            if(y-1>0)    myqueue.push_back(arr[y-1][x]);
            if(x+1<=M)   myqueue.push_back(arr[y][x+1]);
            if(y+1<=N)   myqueue.push_back(arr[y+1][x]);
        }
    }
}

【讨论】:

  • n=newC; 应该类似于arr[y][x]=newC,否则您不会使用新颜色更新数组。您还需要将 x+y 坐标推送到队列中,而不是字符,以便知道在 while 循环的每次迭代中您正在处理的元素。
猜你喜欢
  • 1970-01-01
  • 2014-09-26
  • 2012-05-02
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 2015-05-20
  • 2014-09-13
相关资源
最近更新 更多