Java 将多重递归法转化为迭代法

Java 将多重递归法转化为迭代法,java,recursion,iteration,stack-overflow,Java,Recursion,Iteration,Stack Overflow,我知道类似的答案已经被问过很多次了,但我的情况并没有那么简单 我有一个递归方法,它可以调用自己4次(“最坏情况”)。我正在努力避免递归,因为它会导致StackOverFlowException,但我找不到一种方法用while循环或类似的东西来替换它 这可能吗?据我所知,使用while循环只能向一个方向移动,而不是向所有方向“流动”(实际上是深度优先搜索) 代码如下: private static void searchNeighboringPixels(int x, int y, int[][]

我知道类似的答案已经被问过很多次了,但我的情况并没有那么简单

我有一个递归方法,它可以调用自己4次(“最坏情况”)。我正在努力避免递归,因为它会导致StackOverFlowException,但我找不到一种方法用while循环或类似的东西来替换它

这可能吗?据我所知,使用while循环只能向一个方向移动,而不是向所有方向“流动”(实际上是深度优先搜索)

代码如下:

private static void searchNeighboringPixels(int x, int y, int[][] arr) {
        arr[y][x] = 2;
        if (x+1 < arr[y].length && arr[y][x+1] == 1) {
            searchNeighboringPixels(x+1, y, arr);
            //...do other things
        }
        if (x-1 > 0 && arr[y][x-1] == 1) {
            searchNeighboringPixels(x-1, y, arr);
            //...do other things
        }
        if (y+1 < arr.length && arr[y+1][x] == 1) {
            searchNeighboringPixels(x, y+1, arr);
            //...do other things
        }
        if (y-1 > 0 && arr[y-1][x] == 1) {
            searchNeighboringPixels(x, y-1, arr);
            //...do other things
        }
    }
private static void searchneighborringpixels(int x,int y,int[]arr){
arr[y][x]=2;
如果(x+10&&arr[y][x-1]==1){
搜索相邻像素(x-1,y,arr);
//…做其他事情
}
如果(y+10&&arr[y-1][x]==1){
搜索相邻像素(x,y-1,arr);
//…做其他事情
}
}
我在这里做什么:

private static void searchNeighboringPixels(int x, int y, int[][] arr) {
        arr[y][x] = 2;
        if (x+1 < arr[y].length && arr[y][x+1] == 1) {
            searchNeighboringPixels(x+1, y, arr);
            //...do other things
        }
        if (x-1 > 0 && arr[y][x-1] == 1) {
            searchNeighboringPixels(x-1, y, arr);
            //...do other things
        }
        if (y+1 < arr.length && arr[y+1][x] == 1) {
            searchNeighboringPixels(x, y+1, arr);
            //...do other things
        }
        if (y-1 > 0 && arr[y-1][x] == 1) {
            searchNeighboringPixels(x, y-1, arr);
            //...do other things
        }
    }
  • 在“二进制图片”(在本例中,它被转换为2D int数组)中,我在特定图片周围寻找黑色像素,直到得到所有连接的黑色像素
  • 黑色的值为1,白色的值为0。我已经访问过的像素将设置为值2(用于以后的处理)
  • 该算法进行“深度优先搜索”,直到找到所有连接的黑色像素(并排)

  • 使用堆栈始终可以避免递归:

    • 将点(x,y)放入堆栈中,而不是递归调用
      SearchNeighborringPixels(x,y,arr)

    • 用while循环包装您的4个条件,该循环运行直到堆栈为空

    • 每次迭代都会弹出堆栈顶部,并将该点视为当前点

    大概是这样的:

    private static void searchNeighboringPixels(int x, int y, int[][] arr) {
        Stack<Point> points = new Stack<>();
        points.push(new Point(x,y));
        while (!points.isEmpty()) {
            Point p = points.pop();
            x = p.getX();
            y = p.getY();
            arr[y][x] = 2;
            if (x+1 < arr[y].length && arr[y][x+1] == 1) {
                points.push(new Point(x+1,y);
                //...do other things
            }
            if (x-1 > 0 && arr[y][x-1] == 1) {
                points.push(new Point(x-1,y);
                //...do other things
            }
            if (y+1 < arr.length && arr[y+1][x] == 1) {
                points.push(new Point(x,y+1);
                //...do other things
            }
            if (y-1 > 0 && arr[y-1][x] == 1) {
                points.push(new Point(x,y-1);
                //...do other things
            }
        }
    }
    
    private static void searchneighborringpixels(int x,int y,int[]arr){
    堆栈点=新堆栈();
    推(新点(x,y));
    而(!points.isEmpty()){
    p点=points.pop();
    x=p.getX();
    y=p.getY();
    arr[y][x]=2;
    如果(x+10&&arr[y][x-1]==1){
    点。推(新点(x-1,y);
    //…做其他事情
    }
    如果(y+10&&arr[y-1][x]==1){
    点。推(新点(x,y-1);
    //…做其他事情
    }
    }
    }
    
    您说您正在进行深度优先搜索。有许多定义良好的迭代方法可以解决此问题,大多数方法都基于方法中本地持有的某种形式的
    队列或
    堆栈,而不是调用堆栈。如您所知,基于队列的方法的优点是队列可以不会像递归解决方案那样受到堆栈空间的限制

    此排序深度优先搜索的伪代码:

    DFS的非递归实现:[6]

    输入:图G和G的顶点v

    输出:从标记为已发现的v可到达的所有顶点

    1  procedure DFS-iterative(G,v):
    2      let S be a stack
    3      S.push(v)
    4      while S is not empty
    5            v = S.pop() 
    6            if v is not labeled as discovered:
    7                label v as discovered
    8                for all edges from v to w in G.adjacentEdges(v) do
    9                    S.push(w)
    

    +1谢谢你的工作,但我的目标不是先进行depht搜索。这只是我使用递归实现时的“状态”。我只需要一种“流动”的方法,而不是“从左到右,从上到下”(比如看书)。我认为我的英语还是很差。:)请注意,使用该方法会稍微改变结果,这在某些情况下可能非常重要(例如需要按字典顺序进行连接中断)。此线程讨论了非常类似的问题中的变化:。快速修复方法是在每次迭代中按递归的相反顺序将元素推送到堆栈中。相关: