简体   繁体   中英

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. 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.

    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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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