目录
一.递归的概念
简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
二.递归的调用机制
1)打印问题
public class testRecursion {
public static void main(String[] args) {
print(5);
}
public static void print(int n) {
if (n > 2)
print(n - 1);
System.out.println(n);
}
}
输出结果:
2
3
4
5
2)阶乘问题
public class testRecursion {
public static void main(String[] args) {
int factorial = factorial(5);
System.out.println(factorial);
}
public static int factorial(int n) {
if (n > 1)
return n * factorial(n - 1);
else
return 1;
}
}
输出结果:
120
递归调用规则:
1.当程序执行到一个方法时,就会开辟一个独立的空间(栈)
2.每个空间的数据(局部变量),是独立的.
三.使用递归需要注意的问题
1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间).
2)方法的局部变量是独立的,不会相互影响,比如n变量.
3)如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
4)递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死归了:)
5)当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
四.递归相关问题之迷宫问题
1.迷宫模型
对如图所示的迷宫,需要找到箭头所对的出路,该如何设计
2.问题分析
对于迷宫问题,我们应该使用递归来解决,先做如下规定:
当map,0表示该点没有走过,1表示墙;2表示经走过,3表示走过但是走不通
在走迷宫时,需要确定一个策略(方法) 下->右->上->左,如果走不通,回溯
我们要用二维数组来模拟迷宫的模型,如图所示为设置的一个迷宫
其中1为墙,为不能走的部分.当我们的出发(1,1)位置的时候,根据我们设定的策略,我们首先是朝下面行进的,到达(2,1)位置,之后再向下面行进,发现此路不通,此时应该返回(2,1)位置,之后根据策略朝右走,到达(2,2),以此类推,…….之后到达了(4,3)的位置,发现下,左,右都不可走,而且上面的路已经走过,说明此时路为死路,置此位置为3,之后返回(3,3)位置,同样为死路,以此类推,最后可以到达最终位置(6,5)的位置,返回true,可以找到出路.
3.代码实现
public class maze {
public static void main(String[] args) {
//创建一个二维数组模拟迷宫
int[][] map = new int[8][7];
//使用不同项目表示墙
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
map[4][2] = 1;
map[5][3] = 1;
map[4][4] = 1;
map[3][4] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
//使用递归回溯给小人找路
findRoad(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();
}
}
//使用递归给小球找路
/**
* @param map 地图
* @param i 开始的行
* @param j 开始的列
* (i,j)表示开始的位置
* 如果小球能到(6,5)的位置,返回true,否则返回false
* 约定:当map,0表示该点没有走过,1表示墙;2表示经走过,3表示走过但是走不通
* 在走迷宫时,需要确定一个策略(方法) 下->右->上->左,如果走不通,回溯
* @return
*/
public static boolean findRoad(int[][] map, int i, int j) {
if (map[6][5] == 2) //表示通路已经走过
return true;
else {
if (map[i][j] == 0) {
map[i][j] = 2;
if (findRoad(map, i + 1, j)) {//向下走
return true;
} else if (findRoad(map, i, j + 1)) {//向右走
return true;
} else if (findRoad(map, i - 1, j)) {//向上走
return true;
} else if (findRoad(map, i, j - 1)) {//向左走
return true;
} else {
//说明此路走不通,是死路
map[i][j] = 3;
return false;
}
} else
return false;
}
}
}
结果
2即为使用此策略走出来的路径
4.问题的拓展
已知迷宫,求最短路径.
我们可以知道,迷宫路径的长短只和我们设定的策略有关,只需要对比每一种策略的路径长度,选出最短的那一种即可.总共有24种策略,需要统计出24种,然后进行比较.代码省略
五.递归相关问题之八皇后问题
1.八皇后问题介绍
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,
即:任意两个皇后都不能外干同一行、同一列或同一斜线上,问有多少神摆法。
2.八皇后问题算法思路分析
1)第一个皇后先放第一行第一列
2)第二个皇后放在第二行第一列、然后判断是否OK,如果不OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
3)继续第三个皇后,还是第一列、第二列…..直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
4)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.
5)然后回头继续第一个皇后放第二列,后面继续循环执行1,2,3,4的步骤【示意图】
说明:理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,
用一个一维数组即可解决问题. arr[8] = {0 ,4,7,5,2,6,1,3}//对应arr下标表示第几行,即第几个皇后,arr[i]= val , val表示第i+1个皇后放在第i+1行的第val+1列
3.代码的实现
public class Queue {
//定义一个max表示有多少个皇后
int max = 8;
//定义一个数组array,保存皇后放置位置的结果
int[] arr = new int[max];
static int count = 0;
public static void main(String[] args) {
Queue queue = new Queue();
queue.check(0);
System.out.println("总共有" + count + "种解法");
}
//编写一个方法,放置第n个皇后
//每一次check方法里面,都有依次for循环,因此会有回溯
public void check(int n) {
if (n == max) { //n==8,其实
print();
return;
}
//依次放入皇后,并判断是否冲突
for (int i = 0; i < max; i++) {
//先把当前这个皇后n,放在第i列
arr[n] = i;
//判断放置当前皇后n到第i行时,是否冲突
if (judge(n)) { //不冲突
check(n + 1);
}
//如果冲突,就继续执行arr[n]=i,将此皇后放置在第i+1个位置
}
}
//查看当我们放置第n个皇后,就去检测该皇后是否与前n-1个冲突
public boolean judge(int n) {
for (int i = 0; i < n; i++) {
//在同一列,或者在同一条斜线,则不满足条件返回false
if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
return false;
}
}
return true;
}
//写一个方法,可以将皇后摆放的位置输出
public void print() {
count++;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
打印结果
4.问题的分析
虽然递归解决八皇后问题代码简单,但是运算的量很大,需要上千次判断
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/101081.html