深度优先搜索递归调用导致StackOverflow错误

问题描述

为了解决迷宫,我使用深度优先搜索算法的实现方式进行了迷宫。我不希望找到最短的路径,而是希望找到有效路径的最快方法。这是我用来解决迷宫的方法。迷宫是2d个int数组,其中0是空心正方形,1是墙壁,2是访问过的正方形,9是目的地。
    public class DepthAlgorithm {

/**
 * This method returns true when a path is found. It will also fill up the
 * list with the path used. It will start from (xn,yn,.....,x2,y2,x1,y2)
 * because it will use recursion.
 * @param maze 2d array of maze
 * @param x the x of the starting position
 * @param y the y of the starting position
 * @param path a List of the path
 * @return True if a path is found
 */
public static boolean searchPath(int [][] maze,int x,int y,List<Integer> path){
    // Check if the destination (9) is reached
    if (maze[y][x] == 9) {
        path.add(x);
        path.add(y);
        return true;
    }

    // When the current position is not visited (0) we shall make it visited (2)
    if (maze[y][x] == 0) {
        maze[y][x] = 2;

        //Here we visit all neighbour squares recursively and if a path is found
        // we shall fill the path list with the current position.
        int dx = -1;                // Start and search from starting
        int dy = 0;                 // position (x-1,y)
        if (searchPath(maze,x + dx,y + dy,path)) {
            path.add(x);
            path.add(y);
            return true;
        }

        dx = 1;                    // Start and search from starting
        dy = 0;                    // position (x+1,path)) {
            path.add(x);
            path.add(y);
            return true;
        }

        dx = 0;                   // Start and search from starting
        dy = -1;                  // position (x,y-1)
        if (searchPath(maze,path)) {
            path.add(x);
            path.add(y);
            return true;
        }

        dx = 0;                   // Start and search from starting
        dy = 1;                   // position (x,y+1)
        if (searchPath(maze,path)) {
            path.add(x);
            path.add(y);
            return true;
        }
    }
    return false;
}

}

我的算法适用于小迷宫大小。当我想解决一个50 * 50的迷宫时,它很快。当我移至500 * 500时,出现堆栈溢出错误。我可以理解它是由于函数的许多递归调用而出现的,但是我不知道如何解决它。 有没有其他方法可以使我仍然可以使用深度优先搜索并存储路径,但是没有堆栈溢出?还是可以对我的代码进行任何更改,以便对其进行修复?

public class MazeRunner {

// Maze is a 2d array and it has to be filled with walls peripherally
// with walls so this algorithm can work. Our starting position in this
// will be (1,1) and our destination will be flagged with a 9 which in
// this occasion is (11,8).
private int[][] maze ;
private final List<Integer> path = new ArrayList<>();
public long startTime,stopTime;

public MazeRunner(int [][] maze){
    this.maze = maze;
}

public void runDFSAlgorithm(int startingX,int startingY){
    startTime = System.nanoTime();
    DepthAlgorithm.searchPath(maze,startingX,startingY,path);
    stopTime = System.nanoTime();
    printPath();
    System.out.println("Time for Depth First Algorithm: "+((double) (stopTime-startTime) / 1_000_000)+" milliseconds");

}

public void printPath(){
    ListIterator li = path.listIterator(path.size());
    int lengthOfPath = (path.size()/2-1);
    int fromX,fromY,bool = 0,toX = 0,toY = 0,i = 2;
    while(li.hasPrevious()){
        if (bool == 0) {
            fromX = (int) li.previous();
            fromY = (int) li.previous();
            toX = (int) li.previous();
            toY = (int) li.previous();
            System.out.println("From ("+fromY+","+fromX+") to ("+toY+","+toX+")");
            bool++;
            continue;
        }
        if (bool == 1){
            fromX = toX;
            fromY = toY;
            toX = (int) li.previous();
            toY = (int) li.previous();
            System.out.println("From ("+fromY+","+toX+")");
            i++;
        }
    }
    System.out.println("\nLength of path is : "+lengthOfPath);
}

public static void main(String[] args){
    int [][] maze = {{1,1,1},{1,9,1}};
   MazeRunner p = new MazeRunner(maze);
   p.runDFSAlgorithm(startingPoint[0],startingPoint[1]);
}

}

这是我用于测试的课程。它肯定适用于此示例,但不适用于更大的数组。 任何建议将不胜感激。当我在大型数组上运行程序时,出现以下错误:

error messages

解决方法

通常来说,只有两种可能性会导致stackoverflow异常 1.堆栈内存不足 2.存在一个死循环,在使用递归意味着不存在结束条件。

由于您一直在为小型迷宫工作。可能是原因之一。如您所知,递归规则是后进先出的,在JVM中,所有未执行函数的数据都将存储在堆栈中,堆栈的内存比堆小得多。

,

除非确定可以将堆栈的深度限制为合理的数量,否则切勿在实际工作中使用递归算法。通常,这意味着最多O(log N)或O(log ^ 2 N)。

用于500x500迷宫的DFS可能会在堆栈上放置大约250000个函数调用,这太多了。

如果确实愿意,可以使用DFS,但应在单独的数据结构中维护自己的堆栈。不过,BFS会更好,除非出于某些原因您确实不想要最短的路径。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...