java - 深度优先搜索递归调用导致 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,y)
if (searchPath(maze, x + dx, y + dy, 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, x + dx, y + dy, 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, x + dx, y + dy, path)) {
path.add(x);
path.add(y);
return true;
}
}
return false;
}
}
我的算法适用于小型迷宫。当我想解决一个 50 * 50 的迷宫时,它非常快。当我移动到 500 * 500 时,会出现 Stack Overflow 错误。我可以理解它是由于函数的许多递归调用而出现的,但我不知道如何修复它。有没有另一种方法让我仍然可以使用深度优先搜索并存储我的路径但没有堆栈溢出?或者是否可以在我的代码中进行任何更改以便修复?
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+", "+fromX+") to ("+toY+", "+toX+")");
i++;
}
}
System.out.println("\nLength of path is : "+lengthOfPath);
}
public static void main(String[] args){
int [][] maze = {{1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,0,0,1},
{1,0,1,0,1,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,9,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1}};
MazeRunner p = new MazeRunner(maze);
p.runDFSAlgorithm(startingPoint[0],startingPoint[1]);
}
}
这是我用于测试的课程。它肯定适用于此示例,但对于更大的数组则无效。任何建议将不胜感激。当我在大数组上运行程序时,出现以下错误:
解决方案
一般来说,只有两种可能导致堆栈溢出异常 1.堆栈内存不足 2.存在死循环,使用递归意味着它不存在结束条件。
由于您的算法适用于小型迷宫。这可能是原因之一。如您所知,递归规则是先进后出,在 JVM 中,所有未执行函数的数据都将存储在堆栈中,堆栈的内存比堆小得多。
推荐阅读
- mongodb - 通过索引从对象数组中修改对象并将新对象插入mongodb的同一数组中的有效方法?
- angularjs - 如何从浏览器中的 SAML 响应中获取访问令牌?
- ruby - 在 Windows 中安装 zxing_cpp gem 时 cmake 抛出错误
- oracle - obiee12c RCU 创建失败,Oracle 数据库 19c
- intellij-idea - IntelliJ 在同一个包中显示源文件和测试文件
- c# - StyleBundle 打破相对路径
- wordpress - 如何在 sendgrid wordpress 的联系人列表中添加订阅者?
- php - 我想计算属于同一类别的那些产品的数量
- python - 将带有列表的列拆分为数据框中的多列
- flutter - 在flutter App中首次显示获取的数据时出现问题