To adapt your recursive algorithm in its iterative form, the following minimum changes are needed:
- Use a stack to store the coordinates being visited, the initial value for the stack is the initial coordinates.
- Enter a
while(true)
to all the original code.
- If the stack is empty, then it means there is no output.
- Get the current value of
x
e y
from the top of the stack.
- Run the original algorithm as normal.
- In each recursive call, instead of doing it, add the new values to the stack for
x
e y
, continue
to the next iteration.
- If no recursive call is made, remove the top of the stack and continue to the next iteration.
With these changes the code remains:
public boolean salirIterativo(String[][] lab, int size, int x, int y) {
boolean salio = false;
Deque<Coordenadas> stack = new LinkedList<>();
stack.push(new Coordenadas(x, y));
while (true) {
if(stack.isEmpty()) {
return false;
}
Coordenadas coords = stack.peek();
x = coords.getX();
y = coords.getY();
if (y == size - 1) {
salio = true;
lab[x][y] = "-";
return salio;
} else {
if (!salio && x - 1 > 0 && lab[x - 1][y].equals(" ")) {
lab[x - 1][y] = ".";
//salio = salir(lab, size, x - 1, y);//arriba
stack.push(new Coordenadas(x - 1, y));
continue;
}
if (!salio && y + 1 < size && lab[x][y + 1].equals(" ")) {
lab[x][y + 1] = ".";
//salio = salir(lab, size, x, y + 1);//derecha
stack.push(new Coordenadas(x, y + 1));
continue;
}
if (!salio && x + 1 < size && lab[x + 1][y].equals(" ")) {
lab[x + 1][y] = ".";
//salio = salir(lab, size, x + 1, y);//abajo
stack.push(new Coordenadas(x + 1, y));
continue;
}
if (!salio && y - 1 > 0
&& lab[x][y - 1].equals(" ")) {
lab[x][y - 1] = ".";
//salio = salir(lab, size, x, y - 1);//izquierda
stack.push(new Coordenadas(x, y - 1));
continue;
}
//return salio;
stack.pop();
}
}
}
And the class used for the stack:
private static class Coordenadas {
private final int x;
private final int y;
public Coordenadas(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Execution example:
* Recursivo *
XXXXXXXXXX
X.X.X...XX
X.X.XXX..X
X.X....X.X
X.X.XXXX.X
X.X.XXXX.X
X.X....X.X
X.X.XX.X.X
X...XX...X
XXXXXXXX.-
* Iterativo con stack explicito *
XXXXXXXXXX
X.X.X...XX
X.X.XXX..X
X.X....X.X
X.X.XXXX.X
X.X.XXXX.X
X.X....X.X
X.X.XX.X.X
X...XX...X
XXXXXXXX.-
Code to run example:
public static final String MAZE
= "XXXXXXXXXX\n"
+ "X X X XX\n"
+ "X X XXX X\n"
+ "X X X X\n"
+ "X X XXXX X\n"
+ "X X XXXX X\n"
+ "X X X X\n"
+ "X X XX X X\n"
+ "X XX X\n"
+ "XXXXXXXX \n";
public static String[][] getLab() {
String[] lines = MAZE.split("\n");
if (lines[0].length() != lines.length) {
throw new RuntimeException("Laberinto debe ser cuadrado");
}
int size = lines[0].length();
String[][] lab = new String[size][size];
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
lab[i][j] = String.valueOf(lines[i].charAt(j));
}
}
return lab;
}
private static void print(String[][] lab) {
for (int i = 0; i < lab.length; ++i) {
for (int j = 0; j < lab[i].length; ++j) {
System.out.print(lab[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
System.out.println("* Recursivo *");
String[][] lab = getLab();
new BacktrackingMaze().salir(lab, lab.length, 1, 1);
print(lab);
System.out.println("* Iterativo con stack explicito *");
lab = getLab();
new BacktrackingMaze().salirIterativo(lab, lab.length, 1, 1);
print(lab);
}