递归堆栈溢出&奇数对象参考Java

时间:2016-07-13 16:42:06

标签: java arraylist reference stack-overflow

private boolean[][] computeMainOutline(boolean[][] outline) {

    int pixelValue[][] = new int [width][height];

    for(int x = 0; x < width; x++)
        for(int y = 0; y < height; y++) 
            if(pixelValue[x][y] == 0) {
            ArrayList<Point2D.Double> path = new ArrayList<>();
            findPath(x, y, outline, pixelValue, path );
            }
    return new boolean[1][1]; // to avoid compilation error
}

private void findPath(int x, int y, boolean[][] outline, int pixelValue [][], ArrayList<Point2D.Double> path ) {
    path.add( new Point2D.Double(x, y));

    if(x > 0 && outline[x - 1][y] == true) // check right
        findPath(x - 1, y, outline, pixelValue, path);
    if(x < width && outline[x + 1][y] == true) // check left
        findPath(x + 1, y, outline, pixelValue, path);
    if(y < height && outline[x][y + 1] == true) // check up
        findPath(x, y + 1, outline, pixelValue, path ); 
    if(y > 0 && outline[x][y - 1] == true) // check down
        findPath(x, y - 1, outline, pixelValue, path);
}

上述方法是StackOverflowError,我不知道为什么。

方法computeMainOutline遍历整个outline数组和pixelValue数组,它们的大小相同。如果&#34;值&#34;如果没有针对特定坐标计算,则findPath函数将递归计算路径。路径基本上是多少&#34; true&#34;数组元素彼此相邻。没有添加计算值的方法,但我的第一个问题是找到路径。

此外,如果我在path.add( new Point2D.Double( x, y));之后立即在递归方法中打印path.size()打印语句,则大小顺序可能不一致(1,2,3,4,2,3) ,4),为什么会这样?

更新

像这样纠正了它,但它仍然会引发堆栈溢出......

private boolean[][] computeMainOutline(boolean[][] outline) {

    int pixelValue[][] = new int [width][height];
    boolean visited[][] = new boolean[width][height];

    for(int x = 0; x < width; x++)
        for(int y = 0; y < height; y++) 
            if(visited[x][y] == false) {
            ArrayList<Point2D.Double> path = new ArrayList<>();
            findPath(x, y, outline, pixelValue, path, visited );
            }
    return new boolean[1][1]; // to avoid compilation error
}

private void findPath(int x, int y, boolean[][] outline, int pixelValue [][], ArrayList<Point2D.Double> path, boolean visited [][] ) {
    path.add( new Point2D.Double(x, y));
    visited[x][y] = true;

    if( x > 0  && visited[x - 1][y] == false && outline[x - 1][y] == true) // check right
        findPath(x - 1, y, outline, pixelValue, path, visited);
    if( x < width - 1 &&visited[x + 1][y] == false && outline[x + 1][y] == true) // check left
        findPath(x + 1, y, outline, pixelValue, path, visited);
    if( y < height - 1 && visited[x][y + 1] == false && outline[x][y + 1] == true) // check up
        findPath(x, y + 1, outline, pixelValue, path, visited ); 
    if( y > 0 && visited[x][y - 1] == false && outline[x][y - 1] == true) // check down
        findPath(x, y - 1, outline, pixelValue, path, visited);
}

1 个答案:

答案 0 :(得分:0)

你完成递归的方式是错误的。在进行递归方法时,每次调用都会将前一个调用放在堆栈上。如果您的递归永远运行,那么堆栈中的空间就会不够深,导致堆栈溢出。

这就是问题所在。您没有在每个时间步标记访问过的内容。想象一下这是你的网格。引号中的单元格是我们方法的(x,y)

"T" F F                  T  F F               "T" F F
 T  F F   (next step)   "T" F F    (next)      T  F F
 T  F F                  T  F F                T  F F

它可以追溯到它已经访问过的状态。因此,您将在堆栈中放入无限方法调用。

<强>解决方案

将另一个数组传递给方法,其中包含访问过的单元格,当您转到单元格时将其标记为已访问。这样可以避免你回到之前见过的东西