优化N Queens代码以避免堆栈溢出

时间:2009-07-26 14:35:36

标签: java recursion stack-overflow

我一直在尝试编写一个java类来解决使用某种堆叠和递归的n皇后问题,答案存储在网格(二维数组)中,但我已经遇到了一个死墙,即堆栈n = 8时递归溢出(最大递归深度达到2298) 所以我一直想知道是否有办法通过做一些复杂的事情来绕过这个死者,比如在java中分配更多的堆空间(如果可能的话?)或者使用多线程(指出我的教程/例子)...或者请就如何优化代码提出建议...... 提前致谢

    public void resoudre(){

        this.gridPile.push(copyGrid(grid));
        try{
            int row = gridPile.size()-1;
            if(gridPile.size()==0)row = 0;
            chooseGridSpace(this.grid, locateFirstAvailable(grid, row));
            if(gridPile.size() == this.taille){
                gridSolutions.push(copyGrid(grid));
                grid = gridPile.pop();
                boolean erronous = true;
                while(erronous){
                    try{
                        MakeNextUnavailable(grid, gridPile.size());
                        erronous = false;
                    }
                    catch(UnavailabilityException r1){
                        try{
                            grid = gridPile.pop();
                        }
                        catch(java.util.EmptyStackException r2){
                            return;
                        }
                    }
                }
            }

        }
        catch(InvalidPositionException e1){
            this.grid = gridPile.pop();
            boolean error = true;
            while(error){
                try{
                    MakeNextUnavailable(grid, gridPile.size());
                    error = false;
                }
                catch(UnavailabilityException er){
                    try{
                        this.grid = gridPile.pop();
                    }
                    catch(java.util.EmptyStackException err){
                        return;
                    }
                }
            }
        }
        catch(java.lang.ArrayIndexOutOfBoundsException e2){
            return;
        }
        this.resoudre();
    }

    private static void chooseGridSpace(int[][] grid, Position a){
        grid[a.getLigne()][a.getColonne()] = 1;
        fillNotAvailable(grid, a);
    }

4 个答案:

答案 0 :(得分:4)

直接回答:无需将整个网格推入堆栈,您可能希望将网格表示为8个整数的数组,表示每行的Queen位置。

真正的问题:你的代码太长太复杂了。把事情简单化!女王的问题通常由2个< 10行的函数解决。就像这样简单:

<子>

public static boolean isSolution(final int[] board)
{
    for (int i = 0; i < board.length; i++) {
        for (int j = i + 1; j < board.length; j++) {
            if (board[i] == board[j]) return false;     // same column "|"
            if (board[i]-board[j] == i-j) return false; // diagonal "\"
            if (board[i]-board[j] == j-i) return false; // diagonal "/"
        }
    }
    return true;
}

public static void solve(int depth, int[] board)
{
    if (depth == board.length && isSolution(board)) {
        outputSolution(board);
    }
    if (depth < board.length) {  // try all positions of the next row
        for (int i = 0; i < board.length; i++) {
            board[depth] = i;
            solve(depth + 1, board);
        }
    }
}

添加一些输出代码和一个主程序,你就完成了! <子>

public static void outputSolution(final int[] board)
{
    System.out.println("--- Solution ---");
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[i]; j++) System.out.print(" ");
        System.out.println("Q");
    }
}

public static void main(String[] args)
{
    int n = 8;
    solve(0, new int[n]);
}

答案 1 :(得分:0)

阅读代码,看起来您的程序正在使用Stack&lt; ..&gt;而不是Java递归。因此,它可能耗尽Java堆空间而不是Java堆栈空间。如果是这种情况,您可以使用-Xms和-Xmx选项来增加初始和最大堆大小。

答案 2 :(得分:0)

没有理由在N = 8时达到2298的堆栈深度!

正确的算法是用8个整数的数组来表示皇后,每个整数代表第i个女王的行位置(每列皇后)。

您的最大堆栈大小应为8。

答案 3 :(得分:-3)

在Java中,命令-ss和-oss都可以用来改变堆栈大小。

$java -ss156k (native) 
$java -oss600k (Java) 

参数是您想要的以kbytes或mbytes为单位的堆栈大小。尝试使用一些增加的值,直到不溢出为止。