java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)

最近这学期做了一个java迷宫的课程设计,这里代码及其算法逻辑就分享出来。

首先简单的说一下其中我使用的算法(自动生成地图:递归分割法、递归回溯法;寻找路径:深度优先、广度优先算法)

递归分割法:

地图外面一圈被墙围住,然后在空白区域生成十字墙壁,再随机选择三面墙,将其打通,这样就能保证迷宫的流动性,再分别对刚才分好的四个区域以同样的方式执行分割,一直递归下去,直到空间不足以分割就return。

递归回溯法:

递归回溯法与深度优先算法在大致算法上其实差不多,具体只有一些细微的差别,都是通过判断当前点的是四个方向是否可以通过,当某个点堵住就向上退一步操作。递归回溯法具体算法如下:

(1)初始化,建立一个所有单元格都被墙隔开的迷宫。

(2)从起点开始,以此单元格开始打通墙壁。

(3)以当前单元格为基准,随机选择一个方向,若此方向的邻接单元格没有被访问过,则打通这两个单元格之间的墙壁,并将此单元格作为当前单元格,重复步骤3.

(4)若当前单元格之间的四个邻接单元格都已经被访问过,则退回到进入当前单元格的邻接单元格,且以此单元格为当前单元格,重复步骤3、4。

(5)直至起始点单元格被退回,则算法结束。

深度优先算法和递归回溯差不太多,只是把邻接单元格变为的相邻的单元格,就直接是探寻周围是否有路可走,而不再是打通墙壁了。

广度优先

以步骤为主导,向四周扩散,比如第一步往四周走一格,第二步就四周的那几个单元格再往他们的四周走一格,一直下去,直到找到终点为止,这样返回的就是步骤数,同时因为这是遍历了整个地图,所以找到的一定是最短的路径。

深度优先:

以路径为主导,一直找下去,如果堵住了或者遇到已经访问过的,就返回上一格,随机另一条路继续下去,直到找到终点为止,这种方式找到的路并不是最短的,仅仅提供一条路径而已。

下面是递归分割法、递归回溯法以及文件加载地图实现的类map

//注意看注释,不然可能会看不懂,稍微有点乱

递归分割法:RandomMap1(),genMaze(),OpenADoor()//这三种方法实现,1加载的后面两种方法,2实现十字分割,3实现打开两点为一线之间的一堵墙。

递归回溯法:RandomMap2(),list(),digMaze()//这三种方法实现,1加载的后面两种方法,2连接两格单元格,即把中间的单元格变为通路,3实现如果往下没路可走就返回一个单元格进行继续找路。

文件加载地图:FileMap()方法

package migong;

import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
import java.io.File;

public class Map{
	Random r = new Random();
	int l1,l2;
	int x,y;//在回溯法中代表当前点
	boolean bool2 = true;//使用在getMaze()与list()方法中
	//判断是否执行了第二个if,如果都没执行,说明当前点的相邻点要么被访问过了,要么在边界之外,就需要退一步
	Map(int l1, int l2){
		this.l1 = l1;
		this.l2 = l2;
	}
	Stack<Integer> steps = new Stack<>();

	public int[][] RandomMap2(int l1, int l2){//递归回溯法自动生成迷宫
		//规定0是墙,1是路,2是已经被探寻过的单元,也可以看做路
		int [][] map = new int[l1][l2];
		for(int i = 1;i < l1; i = i + 2) {//初始化迷宫生成所有单元都被墙隔开的迷宫
			for(int j = 1; j < l2;j = j + 2) {
				map[i][j] = 1;
				map[j][i] = 1;
			}
		}
		map[1][1] = 2;
		digMaze(1,1,map);
		return map;
	}
	public boolean list(int x, int y, int[][] map) {//(x,y)代表当前单元格,初始单元格为起点
		this.x = x;
		this.y = y;
		int isOpen = r.nextInt(4);//0代表左边,逆时针旋转
		boolean bool1 = true;
//判断第一个if是否执行,如果四个都没执行,就递归在执行一次,因为有可能随机产生的数过大,把非边界路就已经给排除了

		//分别判断相邻四个点(x,y-2)(x+2,y)(x,y+2)(x-2,y)
		switch(isOpen) {
		case 0:{
			if((this.y-2) > 0 && (this.y- 2) < l2 - 1) {
				bool1 = false;
				if(map[this.x][this.y-2] == 1) {
					map[this.x][this.y-2] = 2;//表示这个点被访问了
					map[this.x][this.y-1] = 1;//打通墙壁
					this.y = this.y - 2;//改变当前点
					bool2 = false;
					steps.push(0);
				}
			}
		}
		case 1:{
			if((this.x+2) > 0 && (this.x+2) < l1 -1) {
				bool1 = false;
				if(map[this.x+2][this.y] == 1) {
					map[this.x+2][this.y] = 2;
					map[this.x+1][this.y] = 1;
					this.x = this.x + 2;
					bool2 = false;
					steps.push(1);
				}
			}
		}
		case 2:{
			if((this.y+2) > 0 && (this.y+2) < l2 - 1) {
				bool1 = false;
				if(map[this.x][this.y+2] == 1) {
					map[this.x][this.y+2] = 2;
					map[this.x][this.y+1] = 1;
					this.y = this.y + 2;
					bool2 = false;
					steps.push(2);
				}
			}
		}
		case 3:{
			if((this.x-2) > 0 && (this.x-2) < l1 -1) {
				bool1 = false;
				if(map[this.x-2][this.y] == 1) {
					map[this.x-2][this.y] = 2;
					map[this.x-1][this.y] = 1;
					this.x = this.x - 2;
					bool2 = false;
					steps.push(3);
				}
			}
		}
		default:{
			if(bool1) {
				list(this.x,this.y,map);
			}
			}
		}
		return bool2;
	}
	public void digMaze(int x, int y, int[][] map) {
		this.x = x;
		this.y = y;
		this.bool2 = true;
		//不能将bool2定义在list方法中,因为递归调用它会让其变为true但后面switch并不会到第二层if中
		//从而这条注释下面的if就会判断失误

		if(list(this.x,this.y,map)) {
			try {
				switch((int)steps.pop()) {//当当前点的下一点全都被访问了就执行退回操作
				case 0:{
					y = y + 2;
					break;
				}
				case 1:{
					x = x -2;
					break;
				}
				case 2:{
					y = y - 2;
					break;
				}
				case 3:{
					x = x + 2;
				}
				default:
				}
			}catch(Exception ex) {
				return;
			}
		}

//		if(x == l1 - 2 && y == l2 - 2){//判断是否到达终点(l1-2,l2-2)
//			return;
//		}
//		if(map[l1-3][l2-2] == 1 && map[l1-2][l2-3] == 1) {
//			return;
//		}
		if(steps.empty()) {//当起始点操作被退回是结束递归,这样生成的地图对比上面两种要更好些
			return;
		}
		digMaze(this.x,this.y,map);
	}

	public int[][] RandomMap1(int l1, int l2){//递归分割法自动生成迷宫
		int [][] map = new int[l1][l2];
//0代表墙,1代表路
		for(int i = 1; i < l1 - 1; i++) {
			for(int j = 1; j < l2 - 1; j++) {
				map[i][j] = 1;
			}
		}

		genMaze(1,1,l1,l2,map);
		return map;
	}
	private void openAdoor(int x1, int y1, int x2, int y2, int[][] map) {
		//以传参的两点为直线,打开这条线的某一点,分割的点存在于x1~(x2-1)或y1~(y2-1)
		int pos;//打开的那一点

		if(x1 == x2) {
			pos = y1 + r.nextInt((int)((y2 - y1)/2 + 1))*2;//在奇数行开门
			map[x1][pos] = 1;
		}
		else if(y1 == y2) {
			pos = x1 + r.nextInt((int)((x2 - x1)/2 + 1))*2;//在奇数列开门
			map[pos][y1] = 1;
		}
		else {
			System.out.println("错误");
		}
	}
	//x,y代表要分割区域的左上点坐标,l1代表的行数,l2代表的列数
	public void genMaze(int x, int y, int l1, int l2, int[][] map) {
		int Xpos, Ypos;

		if(l1 <= 3 || l2 <= 3)
			return;

		//Xpos,Ypos只能取(x或y,l - 1)之间的偶数,这里是开区间
		//横着画线,在偶数位置画线,
		Xpos = x + r.nextInt((int)(l1/2) - 1)*2 + 1;//Xpos,Ypos相当于两条分割线交叉点的坐标
			for(int i = y; i < y + l2 - 2;i++) {
				map[Xpos][i] = 0;
			}
		//竖着画一条线,在偶数位置画线
		Ypos = y + r.nextInt((int)(l2/2) - 1)*2 + 1;
			for(int i = x; i < x + l1 - 2;i++) {
				map[i][Ypos] = 0;
			}

		//随机开三扇门,左侧墙壁为1,逆时针旋转
		int isClosed = r.nextInt(4) + 1;
		switch (isClosed)
        {
        case 1://1开234门,依次下去
            openAdoor(Xpos + 1, Ypos, x + l1 - 2, Ypos, map);// 2
            openAdoor(Xpos, Ypos + 1, Xpos, y + l2 - 2, map);// 3
            openAdoor(x, Ypos, Xpos, Ypos, map);// 4
            break;
        case 2:
            openAdoor(Xpos, Ypos + 1, Xpos, y + l2 - 2, map);// 3
            openAdoor(x, Ypos, Xpos, Ypos, map);// 4
            openAdoor(Xpos, y, Xpos, Ypos, map);// 1
            break;
        case 3:
            openAdoor(x, Ypos, Xpos, Ypos, map);// 4
            openAdoor(Xpos, y, Xpos, Ypos, map);// 1
            openAdoor(Xpos + 1, Ypos, x + l1 - 2, Ypos, map);// 2
            break;
        case 4:
            openAdoor(Xpos, y, Xpos, Ypos, map);// 1
            openAdoor(Xpos + 1, Ypos, x + l1 - 2, Ypos, map);// 2
            openAdoor(Xpos, Ypos + 1, Xpos, y + l2 - 2, map);// 3
            break;
        default:
            break;
        }
		//左上角
		genMaze(x, y, Xpos + 2 - x, Ypos + 2 - y, map);
		//右上角
		genMaze(x, Ypos + 1, Xpos + 2 - x, l2 - Ypos, map);
		//左下角
		genMaze(Xpos + 1, y, l1 - Xpos, Ypos + 2 - y, map);
		//右下角
		genMaze(Xpos + 1, Ypos + 1, l1 - Xpos , l2 - Ypos, map);
	}

	public static int[][] FileMap(String filename) throws Exception{//手动生成迷宫的方法
		//读取没有空格的数字方阵
		File file = new File(filename);
		if(!file.exists()) {
			System.out.println("文件不存在");
		}
		Scanner input = new Scanner(file);
		int l1 = 0, l2 = 0;//l1代表行数,l2代表列数
		String[] str = new String[1024];
		while(input.hasNext()) {
			str[l1++] = input.nextLine();//获取行数同时把每一行分别赋给str数组的各个元素
		l2 = str[0].length();
		}
		int [][]map = new int[l1][l2];
		for(int i = 0;i < l1;i++) {
			for(int j = 0; j < l2;j++) {
				map[i][j] = str[i].charAt(j) - '0';//通过两个Ascll码之差获得其数值
//				map[i][j] = Integer.parseInt(str[i].charAt(j) + "");
			}
		}
		input.close();
		return map;
	}

	public void show(int[][] map,int l1,int l2) {
		for(int i = 0; i < l1; i++) {
			for(int j = 0; j < l2; j++) {
				System.out.print(map[i][j] + " ");
			}
			System.out.println("\n");
		}
	}	

	public static void main(String[] args) throws Exception{
//		String filename = "C:\\Users\\21974\\Desktop\\map.txt";
//		for(int i = 0; i < 2; i++) {
//			for(int j = 0; j < 4; j++) {
//				System.out.print(Map.FileMap(filename)[i][j] + " ");
//			}
//			System.out.println("\n");
//		}

		int l1 = 15,l2 = 15;//奇数
		Map m = new Map(l1, l2);
		m.show(m.RandomMap1(l1, l2),l1,l2);
	}
}

下面是深度优先与广度优先的类findpath:

package migong;

import java.util.LinkedList;
import java.util.Stack;

public class findPath {
	public LinkedList<GPS> steps1 = new LinkedList<>();
	public Stack<Integer> steps2 = new Stack<>();
	int x,y;
	public boolean bool = true;
	//判断是否执行了第二个if,如果都没执行,说明当前点的相邻点是墙,要么被访问过了,要么在边界之外,就需要退一步

	public String shortestPath(int[][] map,int l1, int l2){//最优路径
		//创建一个方向数组,方向的优先级为 "下左上右"
		 Direction[] di = new Direction[] {new Direction(1,0),new Direction(0,-1),new Direction(-1,0),new Direction(0,1)};

		 //创建一个字符数组,其中DLUR分别表示向下、向上、向左、向右走。
		 StringBuffer[] step = new StringBuffer[] {new StringBuffer("D"),new StringBuffer("L"),new StringBuffer("U"),new StringBuffer("R")};

	     //创建一个标识符,判断迷宫是否有解
	     boolean b = false;

        int x=1,y=1,stepNumber=0;
        String startStep = "";//代表空,没有操作
        GPS temp = new GPS(x,y,stepNumber,startStep);  //将起始点的信息加入队列
        map[x][y] = 2;                              //将当前位置标记为已经走过
        steps1.addLast(temp);

        Loop:while(!steps1.isEmpty()) {

       	 temp = steps1.poll() ;    //弹出队头元素进行扩展

       	 for(int i=0;i<4;i++) {    //按照优先级"下左上右",依次进行扩展
       		 int row = temp.x + di[i].inc_x;
       		 int col = temp.y + di[i].inc_y;
       		StringBuffer ts = step[i]; //当前方向的字母表示//当前方向的字母表示

       		 if(map[row][col] == 1) {
       			 int tempStepNumber = temp.stepNumber+1;
       			String tempStepPath = temp.stb + ts;
       			 steps1.addLast(new GPS(row,col,tempStepNumber,tempStepPath)); //符合条件的坐标加入队列

       			 map[row][col] = 2;   //将该结点的值设为2,扩展该结点

       			 if(row == l1-2 && col == l2-2) {  //判断是否到达了终点
       				 b = true;
       				 break Loop;        //跳出标记所在的循环
       			 }
       		 }
       	 }
        }
        if(b) {
        	return steps1.getLast().stb;
        }else {return "无解";}
	}
	public void sMove(int x, int y, int[][] map) {

	}

	public Stack<Integer> path(int x, int y, int[][] map){//深度优先自动寻路
		map[1][1] = 3;
		searchMaze(x,y,map);
		return this.steps2;
	}
	public boolean move(int x, int y,int[][] map){
			//分别判断相邻四个点(x,y-1)(x+1,y)(x,y+1)(x-1,y)
			switch(0) {//0代表左,逆时针
			case 0:{
				if((this.y-1) > 0 && (this.y- 1) < map[0].length - 1) {
					if(map[this.x][this.y-1] == 1 || map[this.x][this.y-1] == 2) {
//0代表墙,1代表路,2代表生成迷宫时被访问了的路,在这里也相当于路,3代表这里找路时被访问了的路
						map[this.x][this.y-1] = 3;//标明改点已经走过了
						this.y = this.y - 1;//改变当前点
						bool = false;
						steps2.push(0);
						break;
					}
				}
			}
			case 1:{
				if((this.x+1) > 0 && (this.x+1) < map.length -1) {
					if(map[this.x+1][this.y] == 1 || map[this.x+1][this.y] == 2) {
						map[this.x+1][this.y] = 3;
						this.x = this.x + 1;
						bool = false;
						steps2.push(1);
						break;
					}
				}
			}
			case 2:{
				if((this.y+1) > 0 && (this.y+1) < map[0].length - 1) {
					if(map[this.x][this.y+1] == 1 || map[this.x][this.y+1] == 2) {
						map[this.x][this.y+1] = 3;
						this.y = this.y + 1;
						bool = false;
						steps2.push(2);
						break;
					}
				}
			}
			case 3:{
				if((this.x-1) > 0 && (this.x-1) < map.length - 1) {
					if(map[this.x-1][this.y] == 1 || map[this.x-1][this.y] == 2) {
						map[this.x-1][this.y] = 3;
						this.x = this.x - 1;
						bool = false;
						steps2.push(3);
						break;
					}
				}
			}
			default:
			}
		return bool;
	}
	public void searchMaze(int x, int y, int[][] map) {//这里是空返回,以后要调用栈直接用类名加数据名
		this.x = x;
		this.y = y;
		this.bool = true;
		if(move(this.x,this.y,map)) {
			try {
				switch((int)steps2.pop()) {//当当前点的下一点全都被访问了就执行退回操作
				case 0:{
					this.y = y + 1;
					break;
				}
				case 1:{
					this.x = x - 1;
					break;
				}
				case 2:{
					this.y = y - 1;
					break;
				}
				case 3:{
					this.x = x + 1;
				}
				default:
				}
			}catch(Exception ex) {
				return;
			}
		}

		if(map[map.length - 2][map[0].length - 2] == 3){//判断是否到达终点(l1-2,l2-2)
			return;
		}
		searchMaze(this.x,this.y,map);
	}

	public void show(Stack<Integer> stack) {
		while(!stack.empty()) {
			System.out.println((int)stack.pop());
		}
	}
	public static void main(String[]args) {
		int l1 = 5,l2 = 5;

		Map m = new Map(l1,l2);
		findPath find = new findPath();

		int[][] map = m.RandomMap1(l1, l2);
//		String s = find.path(l1,l2,map);
//		System.out.println(s);
//		System.out.println("地图为");
//		m.show(map, l1, l2);
		find.path(1,1,map);
		System.out.println("路为");
		m.show(map, l1, l2);
		find.show(find.steps2);
	}
}
class Direction{
	int inc_x;   //x方向的增量
	int inc_y;   //y方向的增量

	public Direction(int inc_x,int inc_y) {
		this.inc_x = inc_x;
		this.inc_y = inc_y;
	}
}

/*
GPS类,成员变量x,y表示坐标,stepNumber表示步数
*/
class GPS{
	int x;
	int y;
	int stepNumber;
	String stb;    //用来记录路径

	public GPS(int x,int y,int stepNumber,String stb){
		this.x = x;
		this.y = y;
		this.stepNumber = stepNumber;
		this.stb = stb;
	}
}

能看到这里说明我的文章对你有所帮助,支持一下呗,第一次写博客有些还不够规范。

到此这篇关于java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)的文章就介绍到这了,更多相关java迷宫算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java寻找迷宫路径的简单实现示例

    迷宫项目实现设计文档 项目介绍: 一个网格迷宫由n行m列的单元格组成,每个大院个要么是空地(用0表示),要么是障碍物(用1表示).你的任务是找一条从起点到终点的移动序列,其中只能上下左右移动到相邻单元格.任何时候都不能在有障碍物的单元格中,也不能走到迷宫之外.起点为左上角和终点右下角. 项目功能: 解决迷宫路径查找问题,寻找一条从左上角迷宫入口到右下角迷宫出口的一条有效路径,0代表可走,1代表不能行走,找到请输出最终的迷宫和路径信息,找不到请输出不存在有效路径. 项目所用知识点: 采用Java面

  • Java实现的迷宫游戏

    完整项目地址: https://github.com/richenyunqi/Maze-game 软件总体框架 该软件主要分为如下三个模块: 参数设置模块 按钮功能模块按钮功能模块 迷宫主界面模块迷宫主界面模块 软件各模块介绍 参数设置模块 1.迷宫大小相关参数: ROWS(即迷宫行数,默认设置为奇数,最小值为11,最大值为99,默认值为11): COLS(即迷宫列数,默认设置为奇数,最小值为11,最大值为99,默认值为11): Lattice's width(即组成迷宫的格子的宽度,迷宫格子默

  • Java编写迷宫小游戏

    缘起: 去年(大三上学期)比较喜欢写小游戏,于是想试着写个迷宫试一下. 程序效果: 按下空格显示路径: 思考过程: 迷宫由一个一个格子组成,要求从入口到出口只有一条路径. 想了一下各种数据结构,似乎树是比较合适的,从根节点到每一个子节点都只有一条路径.假设入口是根节点,出口是树中某个子节点,那么,从根节点到该子节点的路径肯定是唯一的. 所以如果能构造一棵树把所有的格子都覆盖到,也就能够做出一个迷宫了. 另外还要求树的父节点和子节点必须是界面上相邻的格子. 在界面显示时,父节点和子节点之间共用的边

  • Java小项目之迷宫游戏的实现方法

    项目要求: 一个网格迷宫由n行n列的单元格组成,每个大院个要么是空地(用0表示),要么是障碍物(用1表示),你的任务是找一条从起点到终点的移动序列,其中只能上下左右移动到相邻单元格.任何时候都不能在有障碍物的单元格中,也不能走到迷宫之外,起点为左上角和终点右下角. 项目功能: 解决迷宫路径查找问题,寻找一条从左上角迷宫入口到右下角迷宫出口的一条有效路径,0代表可走,1代表能走,找到请输出最终的迷宫和路径信息,找不到请输出不存在有效路径. 思路: 1.定义一个迷宫节点类型(MazeNode)的二维

  • Java遗传算法之冲出迷宫

    遗传算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法.它能解决很多问题,比如数学方程的最大最小值,背包问题,装箱问题等.在游戏开发中遗传算法的应用也十分频繁,不少的游戏 AI 都利用遗传算法进行编码. 就个人理解,遗传算法是模拟神奇的大自然中生物"优胜劣汰"原则指导下的进化过程,好的基因有更多的机会得到繁衍,这样一来,随着繁衍的进行,生物种群会朝着一个趋势收敛.而生物繁衍过程中的基因杂交和变异会给种群提供更好的基因序列

  • java 实现迷宫回溯算法示例详解

    用一个7 x 7的矩形表示迷宫,0和1分别表示的是通路和障碍.通过设计编写程序找到蓝色小球达到蓝色旗子的路线 思路: 构建一个迷宫(用二维数组)实现找通路的方法findRoad() 构建二维数组不难,我们主要是要实现findRoad()这个方法,在实现这个方法前,我们需要约定好一下几个点:小球的位置当作入口(1,1),小旗的位置当作出口(5,5)数组里数的含义分别为(0没有走过).(1障碍).(2走过且为正确的路线).(3走过且为错误的路线)将我们每一步的走法称为策略:下 -> 右 -> 上

  • Java基于深度优先遍历的随机迷宫生成算法

    这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果. 随机迷宫生成我自己的理解简而言之分为以下几步: 1.建立一张地图,我用的二维数组表示,地图上全是障碍物.然后再创建一个用来表示每个格子是否被访问过的二维数组.再创建一个用来表示路径的栈结构. 2.随机选择地图上的一点,呃为了方便我初始点直接取的是左上角即坐标表示为0,0的格子.终点的话因为不涉及到交互就暂时没有. 3.查找当前格子的邻接格(注意,这里的邻接格子都是还未被访问的,下面的代码里有写).

  • 使用栈的迷宫算法java版代码

    本文为大家分享了使用栈的迷宫算法java版,主要考察栈的使用,供大家参考,具体内容如下 主要思路如下: do { if(当前位置可通过) { 标记此位置已走过; 保存当前位置并入栈; if(当前位置为终点) { 程序结束; } 获取下一个位置; } else { if(栈非空) { 出栈: while(当前位置方向为4且栈非空) { 标记当前位置不可走; 出栈; } if(当前位置的方向小于4) { 方向+1; 重新入栈; 获取下一个位置; } } } } while (栈非空); java代码

  • Java项目实现寻找迷宫出路

    本文实例为大家分享了Java实现寻找迷宫出路的具体代码,供大家参考,具体内容如下 项目名称 寻找迷宫出路 项目描述 给定一个自定义迷宫,0表示能通过,1表示不能通过.通过程序找出正确的迷宫出路,并将正确的路线改为2输出. 代码实现 测试类 public class Test { public static void main(String[] args) { Maze maze = new Maze(); maze.begin(); } } 主类:实现主方法 public class Maze

  • java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)

    最近这学期做了一个java迷宫的课程设计,这里代码及其算法逻辑就分享出来. 首先简单的说一下其中我使用的算法(自动生成地图:递归分割法.递归回溯法:寻找路径:深度优先.广度优先算法) 递归分割法: 地图外面一圈被墙围住,然后在空白区域生成十字墙壁,再随机选择三面墙,将其打通,这样就能保证迷宫的流动性,再分别对刚才分好的四个区域以同样的方式执行分割,一直递归下去,直到空间不足以分割就return. 递归回溯法: 递归回溯法与深度优先算法在大致算法上其实差不多,具体只有一些细微的差别,都是通过判断当

  • Java数据结构 递归之迷宫回溯案例讲解

    问题介绍: 用二维数组表示一个迷宫,设置迷宫起点和终点,输出迷宫中的一条通路 实现思路: 二维数组表示迷宫: 0表示路且未走过.1表示墙.2表示通路,3表示已经走过但走不通 设置寻路方法setWay,传入地图和坐标参数 默认方向策略:下.右.上.左 假定传入的店没有走过且可以走通,将其值置为2,然后向下寻路,也就是将坐标 (i + 1, j) 传入寻路方法中 进行递归寻路,向下移动后,再次按照方向策略进行寻路,即再向下寻路,直到遇到死路,即下右左均走不通(因为将走过的路置为2,故向上也走不通,即

  • java二叉树的几种遍历递归与非递归实现代码

    前序(先序)遍历 中序遍历 后续遍历 层序遍历 如图二叉树: 二叉树结点结构 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x){ val=x; } @Override public String toString(){ return "val: "+val; } } 访问函数 public void visit(TreeNode node){ System.out.print(

  • Java 互相关联的实体无限递归问题的解决

    目录 Java 互相关联的实体无限递归 在Jackson2.0以前的解决办法是 好好理解Java中的递归 递归的思想 递归的条件要素 递归的算法结构 递归实战举例 小结一下吧 Java 互相关联的实体无限递归 今天在测试的时候出现了一个bug,在把关联实体序列化返回的过程中报错了,提示 Caused by: java.lang.StackOverflowError: null 这个是堆栈溢出错误,根据错误线索查找,最后发现Column和Table实体互相关联,也就是说 Column实体中有Tab

  • 深入理解python函数递归和生成器

    一.什么是递归 如果函数包含了对其自身的调用,该函数就是递归的.递归做为一种算法在程序设计语言中广泛应用,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量.例如,要计算1-9的9位数字的乘积,直观的算法是1*2*3*4*5*6*7*8*9,如果要计算1-10000的乘积,直观的算法就难于实现出,而递归就可以很简单的实现.请看示例: def fact(n):#计算给定数字到一的乘积 i

  • Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】

    本文实例讲述了Java实现的二叉树常用操作.分享给大家供大家参考,具体如下: import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; //二叉树的建树,前中后 递归非递归遍历 层序遍历 //Node节点 class Node { int element; Node left; Node right; public Node() { } public Node(int element) { this.

  • Java二叉树的四种遍历(递归和非递归)

    二叉树的遍历可以分为前序.中序.后序.层次遍历. 前中后是指何时访问中间节点,即前序遍历,遍历节点的顺序为:中->左->右: 中序遍历,遍历节点的顺序为:左->中->右: 后序遍历,遍历节点的顺序为:左->右->中. 前序遍历 递归实现 public void preorder_Traversal(TreeNode root) { if(root==null)return; //访问节点的逻辑代码块 System.out.print(root.val+" &q

  • java栈实现二叉树的非递归遍历的示例代码

    一般来说遍历二叉树用到递归,但是用Stack进行遍历也是一个不错的方法. 二叉树设置 class Node{ public int val; public Node left; public Node right; public Node(int v) { val=v; left=null; right=null; } } public class Main { public static void main(String[] args) { Node head =new Node(0); No

  • Java中的什么场景使用递归,如何使用递归

    目录 什么是递归? 递归有什么优点? 迭代和递归的区别 递归的三个条件 什么场景下适合使用递归 场景一 场景二 总结 Java 递归算法 一.概述 二.应用场景 三.示例 四.实际示例 五.递归的缺点 什么是递归? 程序调用自身的编程技巧叫做递归. 递归有什么优点? 递归算法:代码简洁.清晰,并且容易验证正确性.在一定的程度上还能帮我们减少很多重复代码. 迭代和递归的区别 迭代是逐渐逼近,用新值覆盖旧值,直到满足条件后结束,不保存中间值,空间利用率高. 递归是将一个问题分解为若干相对小一点的问题

  • c语言 深入理解函数的递归

    前言:  首先,递归是什么,递归就是在定义函数时,然后在函数里调用这个函数,通俗讲,就是函数自己调用自己.那么递归的好处是什么呢?它能够将复杂的问题,用少量的代码来表示,增加了代码的可读性. 但是递归有一个条件,就是每一次的重复调用都需要越接近这个限制条件. 1.用递归打印一个整数的每一位 题目的要求是打印一个整数的每一位,就比如说1234,打印的结果就是1234,我们学过用循环打印过4321,但顺着打印,用循环来做,相对于递归来解,就会有点复杂. #include<stdio.h>//打印一

随机推荐