递归简单来说就是自己调用自己,但是递归一定要有一个出口。否则会不断调用自身导致栈溢出。
调用机制
下边来一个示例代码来看看递归的调用机制
public static void main(String[] args) {//递归简单来讲,就是自己调用自己test(4);//先输出2,再然后3,再然后4}public static void test(int n) {//递归必须有一个出口。if (n > 2) {//再次调用自己。并且 n -1,然后该方法进入阻塞状态。//再次调用的方法会在栈中开辟一个新空间。test(n - 1);}System.out.println("n=" + n);//该段代码,debug一下自然会了解}
如图:

每次调用自身的时候,都会在栈中开辟一个新的区域,然后进入到新的区域重新执行代码。原有的的方法会在test(n - 1) 处变为阻塞状态,等待结果的返回,等待结果返回后,往下继续执行代码。
趁热打铁,用递归实现一下阶乘
public static void main(String[] args) {System.out.println(factorial(3)); // 1 * 2 * 3 = 6}//阶乘问题public static int factorial(int n) {if (n == 1) {return 1;} else {return factorial(n - 1) * n;}}
递归用于解决的问题
一些数学问题,球和篮子,8皇后,哈诺塔,阶乘,迷宫等问题。
还可以在一些算法中使用,比如快排,归并排序,二分查找,分治算法等等。
还可以将用栈解决的问题来简单化。
递归必须要知道的事
- 执行一个方法时,就创建一个新的受保护的独立空间
- 方法的局部变量事独立的,不会相互影响,如果是引用类型(对象)的话就会一起共享
- 递归必须向退出递归的条件逼近,否则就是无限递归,死龟了(哈哈哈哈哈哈)
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用就将结果给谁,同时方法
执行完毕或者返回时,该方法也就执行完毕。
递归实例:迷宫问题
小球在迷宫中找路,迷宫用二维数组代替,规定小球从 (1,1) 开始出发 (6,5)为终点
1表示墙,2表示可以通过,3表示这条路走不通, 0表示还没走过。
确定一条走的策略,下->右->上->左,如果该点走不通就再回溯(比如看看这个点的下方向有没有可能到达最终,如果不可能的话,就回来再变换一个方向)。
现在的迷宫地图为
寻路后的地图应为 —-> 
public static void main(String[] args) {//创建一个二维数组用来模拟迷宫的地图。int [][] map = new int[8][7];//使用1表示墙//上下置为1for (int i = 0; i < 7; i++) {map[0][i] = 1;map[7][i] = 1;}//左右置为1for (int i = 0; i < 7; i++) {map[i][0] = 1;map[i][6] = 1;}//在第四行做一下挡板for (int i = 1; i < 3; i++) {map[3][i] = 1;}//打印一下地图for (int i = 0; i < 8; i++) {for (int j = 0; j < 7; j++) {System.out.print(map[i][j] + " ");}System.out.println();}setWay(map, 1, 1);System.out.println("寻路后的地图:");//打印一下地图for (int i = 0; i < 8; i++) {for (int j = 0; j < 7; j++) {System.out.print(map[i][j] + " ");}System.out.println();}}/*** 小球找路,规定小球从 (1,1) 开始出发 (6,5)为终点* 1表示墙,2表示可以通过,3表示这条路走不通, 0表示还没走过。* 确定一条走的策略,下->右->上->左,如果该点走不通就再回溯。* @param map 表示地图* @param i 从第几行找* @param j 从第几列找* @return 找到路就返回true,否则返回false*/public static boolean setWay(int[][] map, int i, int j) {//map[6][5]代表已经找到通路if (map[6][5] == 2) {return true;} else {//判断当前点的情况。如果为0if (map[i][j] == 0) {map[i][j] = 2;if (setWay(map, i + 1,j)) {//向下走,如果能走通return true;}else if (setWay(map, i, j + 1)){//向右走return true;}else if (setWay(map, i -1 , j)){//向上走return true;}else if (setWay(map, i, j - 1)){//向左走return true;}else {//如果都走不通的话,变为3map[i][j] = 3;return false;}}else {//map[i][j]是其他数字的话,都返回false,不需要我们再走一边。return false;}}}
以上这种地图的排法并没有体现出回溯,如果将map[1][2] = 1,map[2][2] = 1,就会体现出回溯了
——> 
这里简单理解一下回溯就行了,就是试探性的找位置,可以根据树状结构来简单的理解下。
就不贴八皇后代码了,感觉有些抽象。
