基本思想: 用一个方法通过调用自身来实现任务。
注: 为防止发生无穷递归,要设置“基础情形” 程序中通常用 if-else 来实现。
分类:直接递归与间接递归
实例: 走迷宫
思维: 解决迷宫问题要考虑大量的试验和错误,一条路走不通,要回溯,然后尝试另一条路。
思考:如何使用基础情形来结束递归?
目标:创造一个迷宫。 用二维数组来表示。 初始: 1表示通路,0表示不通。目标:从左上角进,从右下角出。
//maze.java
public class maze{
private final int TRIED = 3; // final 关键字定义的变量不可被更改(用大写)
private final int PATH = 7; // 这里我们用 3 表示尝试过的路径,用7表示可以走通的路径
private int[][] grid = {{1,1,1,0,1,1,0,0,0,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1,0,0,1},
{0,0,0,0,1,0,1,0,1,0,1,0,0},
{1,1,1,0,1,1,1,0,1,0,1,1,1},
{1,0,1,0,0,0,0,1,1,1,0,0,1},
{1,0,1,1,1,1,1,1,0,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1}
}; //创建二维数组 作为迷宫
public boolean traverse(int row, int column){
//主函数 只能“上下左右”四个方向走
boolean done = false; //done 表示一条路是否可以走通。 用布尔类型
if (valid(row,column)){ // 调用检测边界函数 (为true还在迷宫内部)
grid[row][column]=TRIED; //该cell被尝试过了
if (row == grid.length-1 && column == grid[0].length-1)
//这是递归的基础情形, 如果达到位置(7,12)说明走出迷宫
//(注 迷宫共8行13列, 而数组是从0开始的)
done = true; // 走出迷宫
else{
done = traverse(row+1,column); //递归调用 往下走
if (!done) //done为false时
done = traverse(row,column+1);//right
if(!done)
done = traverse(row-1,column);//up
if(!done)
done = traverse(row,column-1);//left
}
if (done)
grid[row][colum]=PATH;
}
return done;
}
public boolean valid(int row, int column){
// 判断是否到达迷宫边界
boolean result = false;
if (row>=0 && row<grid.length && column>=0 && column<grid[0].length) //判断cell是否还在迷宫内部
// 二维数组:array.length 第一维的长度
// array[0].length 第二维的长度
if (grid[row][column] == 1){
//检测该cell没有被尝试过或者走过
result = true;
}
return result;
}
public String toString(){
//重写String 以便以要求的格式输出
String redult = "\n";
for (int row=0;row<grid.length;row++){
for(int column=0;row<grid[row].length;column++)
result += grid[row][column]+" "
result += "\n"
}
return result;
}
}
//Mazemain.java
public class Mazemain{
public static void main(String args[]){
maze laby = new maze();
System.out.println(laby);
if (laby.traverse(0,0))
System.out.println("the maze was successfully traversed");
else
System.out.println("no way");
System.out.println(laby)
}
}
实际情况中,用来结束递归的基础情形可能有三种:
1 因为越出边界,导致一个不可行的移动
2 曾经尝试过而导致一个不可行的移动
3 到达最终位置
如果当前位置不是右下角,再从每个基本方向中寻找可行路径。先向下,调用traverse()将新位置作为参数。我们可以认为,每次递归调用,就是开始走一个新的简单一些的迷宫。
下-右-上-左 按照这四个方向 逐步尝试。先尝试从当前位置向下走,如果找不到通路,向右走,如果还是失败,向上走,最后尝试向左走。
如果在当前位置找到通路,则网格中值改为7.
经过不断的递归调用,第一个7写入右下角,下一个7写入能达到右下角的位置,继续该过程,知道最后一个7写入左上角。