递归,玩不好就是死龟~
递归就是函数自己调用自己,在我们的JVM中存在一种叫做方法栈的概念,我们可以简单的理解为我们方法的每次调用执行都有一个独立的空间。递归之所以可以运用在于他一下的几个特性:
在我们递归中对于应用型数据与数值型数据的差异在于我们Java中参数传递的本质都是值传递,一个传递的是他的本身二一个传递的是他的他值的引用。对于这一点的理解便于我们对递归中值的变化有一个基础了解。在使用递归的时候最关键的是要设置跳出递归的一个条件,不然的话就会出现死循环,造成我们的栈溢出。我们使用递归是为了解决问题,在使用递归的时候数据或是问题的处理可以分为在往里递归的时候与回溯的时候。在我们的一层递归中如果在引入递归的位置之后还有代码,那么我们这之后的代码只会等到我们的下一层产生了回溯的时候才会执行我们接下来的代码。
递归、回溯的代码分析
迷宫问题代码实现:
我们迷宫问题就是要在一个模拟的有障碍的房间中找到我们的目标点。这里和动态规划的方法求最短路径是有区别的!
public class MiGong {
public static void main(String[] args) {
//初始化一个二维数组用来存储我们的迷宫地图
final int mapSize = 10;
int[][] miGongMap = new int[mapSize][mapSize];
for (int i = 0; i < mapSize; i++) {
miGongMap[0][i] = 1;
miGongMap[mapSize-1][i] = 1;
miGongMap[i][0] = 1;
miGongMap[i][mapSize-1] = 1;
}
miGongMap[6][7] = 1;
miGongMap[4][8] = 1;
showMap(miGongMap);
searchWay(miGongMap,1,1,3,4);
System.out.println("行走路线图:");
showMap(miGongMap);
}
/**
*@description: 我们设置走路的策略是先上后下,先左后右
*@params: 迷宫的地图以及起始点的坐标与终止点的坐标
*@returns: 此处是否可以走通
*/
public static boolean searchWay (int[][] miGongMap,int startX,int startY,int targetX,int targetY){
if (miGongMap[targetX][targetY]==2){
return true;
}else{
if(miGongMap[startX][startY]==0){//表示我们当前的节点是可以走的,下面置值为2表示我们这个点走过
miGongMap[startX][startY]= 2;
if (searchWay(miGongMap,startX,startY+1,targetX,targetY)){
return true;
}else if(searchWay(miGongMap,startX,startY-1,targetX,targetY)){
return true;
} else if(searchWay(miGongMap,startX-1,startY,targetX,targetY)){
return true;
} else if(searchWay(miGongMap,startX+1,startY,targetX,targetY)){
return true;
}else{
//这一步是回路递归的关键,他会一次的去找走过的节点但是还没有走过的路
return false;
}
}else{
return false;
}
}
}
public static void showMap(int[][] miGongMap){
for (int i = 0; i < miGongMap.length; i++) {
for (int j = 0; j < miGongMap.length; j++) {
System.out.printf(miGongMap[i][j]+" ");
}
System.out.println();
}
}
}
八皇后问题递归代码:
public class Queue8 {
static int count = 0;
final static int queueMax = 8;
//初始化一个一维数组用来存放每次的记录结果
static int [] virtualCheckerboard = new int[queueMax];
public static void main(String[] args) {
// countScheme(0);
countSchemeByFor();
System.out.println("一共有 "+count+" 种执行结果");
}
public static void countScheme(int n){
if(n==queueMax){
showScheme();
return;
}
//下面的这个循环使我们八皇后问题的精华所在
for (int i = 0; i < queueMax; i++) {
virtualCheckerboard[n] = i;
if(isConfict(n)){
countScheme(n+1);
}
}
}
public static void showScheme(){
count++;
System.out.println("这是第 "+count +"方案");
for (int i = 0; i < virtualCheckerboard.length; i++) {
System.out.printf(virtualCheckerboard[i]+" ");
}
System.out.println();
}
public static boolean isConfict(int virtualX){
/**
*@description:
*@params: 当前皇后所处的行
*@returns: 当前所放置的位置是否与前面已经放置了皇后发生冲突
*/
for (int i = 0; i < virtualX; i++) {
if(virtualCheckerboard[i]==virtualCheckerboard[virtualX]||
Math.abs(i-virtualX)==Math.abs(virtualCheckerboard[i]-virtualCheckerboard[virtualX])){
return false;
}
}
return true;
}
}
八皇后问题的八重for循环实现:
public static void countSchemeByFor(){
for (int i = 0; i < queueMax; i++) {
virtualCheckerboard[0] = i;
if(!isConfict(0)){
continue;
}
for (int j = 0; j < queueMax; j++) {
virtualCheckerboard[1] = j;
if(!isConfict(1)){
continue;
}
for (int k = 0; k < queueMax; k++) {
virtualCheckerboard[2] = k;
if(!isConfict(2)){
continue;
}
for (int l = 0; l < queueMax; l++) {
virtualCheckerboard[3] = l;
if(!isConfict(3)){
continue;
}
for (int m = 0; m < queueMax; m++) {
virtualCheckerboard[4] = m;
if(!isConfict(4)){
continue;
}
for (int n = 0; n < queueMax; n++) {
virtualCheckerboard[5] =n;
if(!isConfict(5)){
continue;
}
for (int o = 0; o < queueMax; o++) {
virtualCheckerboard[6] = o;
if(!isConfict(6)){
continue;
}
for (int p = 0; p < queueMax; p++) {
virtualCheckerboard[7]=p;
if(!isConfict(7)){
continue;
}
showScheme();
}
}
}
}
}
}
}
}
}