简体   繁体   English

递归java中的堆栈溢出异常

[英]stack overflow exception in recursion java

My problem is when i change the first parameter into over 300 in line 133, i get a java.lang.StackOverflowError in line 37.This line is a recursion. 我的问题是当我在第133行将第一个参数更改为超过300时,我在第37行得到了一个java.lang.StackOverflowError。这一行是递归。 How can i solve this? 我怎么解决这个问题?

public class PathFindingOnSquaredGrid {

// given an N-by-N matrix of open cells, return an N-by-N matrix
// of cells reachable from the top
public static boolean[][] flow(boolean[][] open) {
    int N = open.length;

    boolean[][] full = new boolean[N][N];
    for (int j = 0; j < N; j++) {
        flow(open, full, 0, j);
    }

    return full;
}

 // determine set of open/blocked cells using depth first search
 public static void flow(boolean[][] open, boolean[][] full, int i, int j) {
    int N = open.length;

    // base cases
    if (i < 0 || i >= N) return;    // invalid row
    if (j < 0 || j >= N) return;    // invalid column
    if (!open[i][j]) return;        // not an open cell
    if (full[i][j]) return;         // already marked as open

    full[i][j] = true;

    flow(open, full, i+1, j);   // down line 37
    flow(open, full, i, j+1);   // right line 38
    flow(open, full, i, j-1);   // left line 39
    flow(open, full, i-1, j);   // up line 40
}

// does the system percolate?
public static boolean percolates(boolean[][] open) {
    int N = open.length;

    boolean[][] full = flow(open);
    for (int j = 0; j < N; j++) {
        if (full[N-1][j]) return true;
    }

    return false;
}

//does the system percolate vertically in a direct way?
public static boolean percolatesDirect(boolean[][] open) {
    int N = open.length;

    boolean[][] full = flow(open);
    int directPerc = 0;
    for (int j = 0; j < N; j++) {
        if (full[N-1][j]) {
            // StdOut.println("Hello");
            directPerc = 1;
            int rowabove = N-2;
            for (int i = rowabove; i >= 0; i--) {
                if (full[i][j]) {
                     //StdOut.println("i: " + i + " j: " + j + " " + full[i][j]);
                    directPerc++;
                }
                else break;
            }
        }
    }

    // StdOut.println("Direct Percolation is: " + directPerc);
    if (directPerc == N) return true; 
    else return false;
}

// draw the N-by-N boolean matrix to standard draw
public static void show(boolean[][] a, boolean which) {
    int N = a.length;
    StdDraw.setXscale(-1, N);;
    StdDraw.setYscale(-1, N);
    StdDraw.setPenColor(StdDraw.BLACK);
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            if (a[i][j] == which)
                StdDraw.square(j, N-i-1, .5);
            else StdDraw.filledSquare(j, N-i-1, .5);
}

// draw the N-by-N boolean matrix to standard draw, including the points A (x1, y1) and B (x2,y2) to be marked by a circle
public static void show(boolean[][] a, boolean which, int x1, int y1, int x2, int y2) {
    int N = a.length;
    StdDraw.setXscale(-1, N);;
    StdDraw.setYscale(-1, N);
    StdDraw.setPenColor(StdDraw.BLACK);
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            if (a[i][j] == which)
                if ((i == x1 && j == y1) ||(i == x2 && j == y2)) {
                    StdDraw.circle(j, N-i-1, .5);

                }
                else StdDraw.square(j, N-i-1, .5);
            else StdDraw.filledSquare(j, N-i-1, .5);
}

// return a random N-by-N boolean matrix, where each entry is
// true with probability p
public static boolean[][] random(int N, double p) {
    boolean[][] a = new boolean[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            a[i][j] = StdRandom.bernoulli(p);
    return a;
}



// test client
public static void main(String[] args) {

    ArrayList<Node> path=null;
    Stopwatch timer;


   // The following will generate a 10x10 squared grid with relatively few 
   obstacles in it
   //The lower the second parameter, the more obstacles (black cells) are 
   generated

In here I was changing gird values to get test cases. 在这里,我正在改变gird值以获得测试用例。

    boolean[][] randomlyGenMatrix = random(350, 0.8); //line133

    StdArrayIO.print(randomlyGenMatrix);
    show(randomlyGenMatrix, true);

    System.out.println();
    //System.out.println("The system percolates: " + percolates(randomlyGenMatrix));

    System.out.println();
    //System.out.println("The system percolates directly: " + percolatesDirect(randomlyGenMatrix));
    System.out.println();


    Stopwatch timerFlow = new Stopwatch();

    Scanner in = new Scanner(System.in);
    System.out.println("Enter i for A > ");
    int Ai = in.nextInt();

    System.out.println("Enter j for A > ");
    int Aj = in.nextInt();

    System.out.println("Enter i for B > ");
    int Bi = in.nextInt();

    System.out.println("Enter j for B > ");
    int Bj = in.nextInt();


 // THIS IS AN EXAMPLE ONLY ON HOW TO USE THE JAVA INTERNAL WATCH
    // Stop the clock ticking in order to capture the time being spent on inputting the coordinates
    // You should position this command accordingly in order to perform the algorithmic analysis
    StdOut.println("Elapsed time = " + timerFlow.elapsedTime());

            //StdDraw.point(Ai, Bj);           

    // System.out.println("Coordinates for A: [" + Ai + "," + Aj + "]");
    // System.out.println("Coordinates for B: [" + Bi + "," + Bj + "]");

    show(randomlyGenMatrix, true, Ai, Aj, Bi, Bj);


     String dis="";
     while(!dis.equalsIgnoreCase("X")){
        //Selecting the path
        System.out.println("Enter Distance: (M)Manhattan|(E)Euclidean|(C)Chebyshev|(X)Exit");         
        dis=in.next();
        timer=new Stopwatch();
        path = new DijkstraAlgorithm(dis).distance(randomlyGenMatrix, Ai, Aj, Bi, Bj);

        System.out.println("Elapsed time: "+timer.elapsedTime());

        //Draw the path in the grid
        for (Node node : path) {
            StdDraw.filledCircle(node.y, 10 - node.x -1, .2);


        }
  }
    System.exit(0);

}

}

The only thing you are using recursion for is to keep track of the locations that need to be checked. 您使用递归的唯一方法是跟踪需要检查的位置。 So you could instead have a queue of those locations, and keep processing the one popped off the head of the queue until the queue is empty. 因此,您可以改为拥有这些位置的队列,并继续处理从队列头部弹出的队列,直到队列为空。 The body of the loop would look like the body of your flow method (except the initial tests would continue the loop instead of return ing), but you would initialize the queue with the initial (i,j) location, and replace the recursive calls with enqueues of those locations. 循环的主体看起来像你的flow方法的主体(除了初始测试将continue循环而不是return ),但你会用初始(i,j)位置初始化队列,并替换递归调用这些地点的队列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM