递归调用导致Java堆栈溢出

递归调用导致Java堆栈溢出,java,algorithm,recursion,Java,Algorithm,Recursion,问题 你好, 我正在做一个Java项目来完成我的大学学业,遇到了一个我自己无法解决的问题,这是我第一次在这里问问题,所以如果我做错了什么,请告诉我 我试图用墙跟随算法来解一个简单连接的迷宫,该算法在迷宫中行走,总是尝试向右转弯,然后向前移动,最后向右转弯。当遇到一个死掉的算法时,它会掉头并开始向后移动 当迷宫大小大于500 x 500时,我的递归运算会导致堆栈溢出错误。我想知道代码中是否有错误,或者用递归算法解决这类问题是不可行的 注意:问题不是算法不起作用,而是它耗尽了堆栈 **问题:** 是

问题

你好,

我正在做一个Java项目来完成我的大学学业,遇到了一个我自己无法解决的问题,这是我第一次在这里问问题,所以如果我做错了什么,请告诉我

我试图用墙跟随算法来解一个简单连接的迷宫,该算法在迷宫中行走,总是尝试向右转弯,然后向前移动,最后向右转弯。当遇到一个死掉的算法时,它会掉头并开始向后移动

当迷宫大小大于500 x 500时,我的递归运算会导致堆栈溢出错误。我想知道代码中是否有错误,或者用递归算法解决这类问题是不可行的

注意:问题不是算法不起作用,而是它耗尽了堆栈

**问题:**

是否存在循环或内存泄漏,或者在一定数量的调用之后不可能使用递归

我有一个迭代的解决方案,可以在任何迷宫大小下工作

节目

迷宫被表示为一个2D数组,每个正方形都有自己的类来保存迷宫中的坐标。我的想法是,当递归方法运行时,Java存储这些方形对象而不清理它们。move()方法调用一个方法getSquareInDirection,该方法创建一个新的Square对象,这可能会导致错误。其他方法只改变枚举方向,不应该是错误的原因,但我不确定这一点

父方法

    public SquareQue solveRecursive() {
        Square start = maze.getStart();
        SquareQue path = new SquareQue();
        move(start, Direction.DOWN, path);

        maze.setSquareValue(start.getWidth(), start.getHeight(), 3);

        return path;
    }
递归方法

public SquareQue move(Square pos, Direction dir, SquareQue path) {
        if (maze.reachedFinish(pos)) {
            path.add(pos);
            return path;
        }

        if (canMove(pos, getDirectionToRight(dir))) {
            pos = getSquareInDirection(pos, getDirectionToRight(dir));
            path.add(pos);
            return move(pos, getDirectionToRight(dir), path);

        } else if (canMove(pos, dir)) {
            pos = getSquareInDirection(pos, dir);
            path.add(pos);
            return move(pos, dir, path);

        } else if (canMove(pos, getDirectionToLeft(dir))) {
            pos = getSquareInDirection(pos, getDirectionToLeft(dir));
            path.add(pos);
            return move(pos, getDirectionToLeft(dir), path);

        } else {
            pos = getSquareInDirection(pos, reverse(dir));
            return move(pos, reverse(dir), path);
        }
    }
Recrsuvie方法调用此

public static Square getSquareInDirection(Square pos, Direction dir) {
        int col = pos.getWidth();
        int row = pos.getHeight();
        if (dir == Direction.UP) {
            return new Square(col, row - 1);
        }
        if (dir == Direction.DOWN) {
            return new Square(col, row + 1);
        }
        if (dir == Direction.RIGHT) {
            return new Square(col + 1, row);
        }
        if (dir == Direction.LEFT) {
            return new Square(col - 1, row);
        }
        return null;
    }

再现错误

复制错误的最简单方法是克隆项目并编辑GUI类

在方法getSolveScene内的GUI类中,并更改按钮设置以调用大型递归结果 方法:

使用例如:
(getSolveScene(501501,12,设置)
重新设置getSolveScene

在此之后,您可以保存并运行带有大型和递归设置的程序


提前感谢您的响应!

默认堆栈大小非常小(至少对于递归算法来说通常太小)。默认值在大多数虚拟机中只有1MByte

要更改堆栈大小,请使用VM参数:-Xss


但要检查堆栈大小是否是您唯一的问题,请先尝试解决一个较小的迷宫。

只要堆栈大小足够大,可以容纳所需的递归深度(这取决于迷宫的大小),递归方法就可以工作


但是,我还看到另一个问题-
getSquareInDirection
似乎没有检查是否返回到已访问的路径。如果发生这种情况,您的程序可能会陷入“循环”即无限递归。请尝试在
move
中打印当前坐标,并查看它们是否重复。(提示:不应该)

您需要显示所有相关代码(最好以最小的可复制方式显示)你能突出你的问题吗?你到底在问什么?你如何确保代码没有在一个圆圈中移动?canMove方法是否检查你是否已经访问了一个正方形?如果你的递归算法适用于相对较小的大小,并抛出StackOverFlow运行时异常,你很可能可以通过。这样,您可以缓存已经计算过的表达式,并将其结果重新用于同一组参数。该算法的目的不是直接跟踪它访问的方块。相反,它使用的逻辑是,始终沿着右边的墙,它最终会到达终点。我认为这并不能回答问题。@Giorgi tsiklauri:我很确定在500x500迷宫中进行递归搜索将导致递归深度可能高于1MB堆栈大小。是的,但这是您在讨论中提出的一个假设,而不是明确解决问题的答案。这是预期的,算法不允许跟踪其访问的方块。循环是通过反转遍历方向避免该算法,它将返回到第一次通过时被忽略的最后一个交叉点,因为当时它是一个左转。@VilleManninen在这种情况下,迷宫必须没有回路或平行路径,即它必须是一棵树。这就是你所说的“简单连接”吗?是的,对不起,我应该说得更清楚一些,这确实是它的意思。为了澄清算法确实解决了生成的迷宫,但使用大型迷宫时内存不足。@VilleManninen在这种情况下,您有一个比默认堆栈更大的合法要求-只需使用类似
java-Xss32m
(根据需要调整大小)的东西即可。
if (selectedString.equals("Large")) {
                    stage.setScene(getSolveScene(81, 81, 12, setting));
                    stage.setTitle("Maze generator - Recursive Large");

                }