面试:BFS解迷宫问题,并打印最短路径

package algorithm;
/* 本例子是:求出迷宫的最短路径
 * 如果是找一点出路而不管远近,则可以用队列来处理,类似二叉树的宽度遍历。
 * 在迷宫问题上,类似在一颗4叉树中,利用遍历去找一条从根到某个节点的路径一样。
 * 方法为:
 * 处理下面的节点,
 * 1:从队列中取出最前面的节点,记为K,直到队列里面没有节点为止。
 * 2:对它的北节点,南节点,西节点,东节点,记为节点M,逐一按下面处理。
 * 2.1:如果M节点未处理,且不是起始点,则设置M节点的路径长度为 K节点的长度+1,把节点M入队列,设置节点M的preNode为K。
 * 2.2:如果M节点被处理过,但是它的长度大于(K节点的长度+1),则设置M节点的路径长度为K节点的长度+1,把节点M入队列,设置节点M 的preNode为K。
 * 2.3:如果是其它情况,都不处理。
 * 3.如果出口节点的长度不为-1,则从出口节点的preNode开始,逐一打印出节点,这些节点就是最短路径上的节点。
 */
import java.util.*;
public class MazeShow {
     public static class MazeNode {
	/* 0 means it is not processed yet or it is entrance point
	 * >0 means the shortest distance from the entrance node  
	 */
	private int distance; 
	/*
	 * data: it is setup during initialization phase.
	 * -1: means this node is wall.
	 * 0: means it can be went through.
	 */
	private int data;
	private int row;
	private int column;
	boolean isStartPoint;
	boolean isExitPoint;
	private MazeNode prevNode;
	
	public MazeNode(){
		distance=0;
		data=0;
		column=0;
		row=0;
		isStartPoint=false;
		isExitPoint=false;
		prevNode=null;
	}
	
	public MazeNode getprevNode(){
		return prevNode;
	}
	public void setprevNode(MazeNode mprevNode){
		prevNode=mprevNode;
	}	
	public int getRow(){
		return row;
	}
	public int getColumn(){
		return column;
	}
	public void setRow(int row){
		this.row=row;
	}
	public void setColumn(int column){
		this.column=column;
	}
	public int getDistance(){
		return distance;
	}
	public void setData(int data){
		this.data=data;
	}	
	public void setDistance(int dis){
		distance=dis;
	}
	public int getData(){
		return data;
	}	
	public void setStartPoint(boolean value){
		isStartPoint=value;
	}
	public void setEndPoint(boolean value){
		isExitPoint=value;
	}
	public boolean getStartPoint(){
		return isStartPoint;
	}
	public boolean getEndPoint(){
		return isExitPoint;
	}
   }
public static int getMazeShortestDistance(){	
		int MAZE_WIDTH=5,MAZE_HEIGHT=5,distance=0;		
	    MazeShow.MazeNode[][] mymaze=new MazeShow.MazeNode[MAZE_HEIGHT][MAZE_WIDTH];
	    for(int height=0;height<MAZE_HEIGHT;height++)
	      for(int width=0;width<MAZE_WIDTH;width++) {
	    	  //Java OBJ array must create new each obj element after TYPE[][] m=new TYPE[5]6];
	    	  mymaze[height][width]=new MazeShow.MazeNode();
	    	  mymaze[height][width].setRow(height);
	    	  mymaze[height][width].setColumn(width);
	    	  mymaze[height][width].setprevNode(null);
	      }
	    
	    //set up as(0,0) as entrance point 	    
	    mymaze[0][0].setData(0);
	    mymaze[0][0].setDistance(0);
	    mymaze[0][0].setStartPoint(true);
//set up as(MAZE_WIDTH-1,MAZE_HEIGHT-1) as exit point 
	    mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].setData(0);
	    mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].setDistance(0);
	    //set maze as below which is wall
	    /*
	     *   
       { 0,  0,  0,  0,  0},    
       {-1,  0, -1,  0, -1},    
       { 0,  0, -1, -1, -1},    
       { 0, -1,  0,  0,  0},    
       { 0,  0,  0, -1,  0},
	     * 
	     */
 mymaze[1][0].setData(-1);	    
	    mymaze[3][1].setData(-1);	    
	    mymaze[1][2].setData(-1);
	    mymaze[2][2].setData(-1);	    
	    mymaze[2][3].setData(-1);
	    mymaze[4][3].setData(-1);	    
	    mymaze[1][4].setData(-1);
	    mymaze[2][4].setData(-1);	    
	    //process now
	    Queue<MazeShow.MazeNode> mazequeue = new LinkedList<MazeShow.MazeNode>();	    
	    //push the entrance point as start point	    
	    mazequeue.offer(mymaze[0][0]);
	    MazeShow.MazeNode pnode=null;	    
	    int pcolumn=0, prow=0;
		MazeShow.MazeNode currentNode=null;
		/*
		 * 1、add()和offer()区别:
          add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。因此就可以在程序中进行有效的判断!
		  2、poll()和remove()区别:
remove() 和 poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null。因此新的方法更适合容易出现异常条件的情况。
		 * *
		 */
	    while(!mazequeue.isEmpty()) {
	    	//get the FIFO node from queue;
	    	currentNode=null;
	    	pnode=mazequeue.poll();	    	
	    	/*依次把上 下 左 右 四个相邻的节点的距离更新后,然后把这些节点送进队列里,处理这4个方向节点完毕后,
	    	 * 再从队列头取一个节点,再次重上上面的处理,直到处理到完所有能从起点开始的节点。
	    	 * */
	    	for(int turn=0;turn<4;turn++) {
	    	 switch(turn) {
	    	  case 0: //left
	    		  if(pnode.getColumn()>0) {
	    			 pcolumn=pnode.getColumn()-1;
	 	    		 prow=pnode.getRow();
	 	    		 currentNode=mymaze[prow][pcolumn];
	    		   }
	    		  else 
	    			  currentNode=null;  
	    		    break;
	    	 case 1: //down	    		 
	 	    	  if(pnode.getRow()<(MAZE_HEIGHT-1)) {
	 	    		// not the lowest node
	 	    		pcolumn=pnode.getColumn();
		 	    	prow=pnode.getRow()+1;
		 	    	currentNode=mymaze[prow][pcolumn];
	 	    	  }
	 	    	  else 
	    			  currentNode=null;  
	    		    break;
	    	 case 2: //right 
	 	    	 if(pnode.getColumn()<(MAZE_WIDTH-1)) {
	 	    		// not the most right node
	 	    		 pcolumn=pnode.getColumn()+1;
	 	    		 prow=pnode.getRow();
	 	    		 currentNode=mymaze[prow][pcolumn];
	 	    	  }
	 	    	 else 
	    			  currentNode=null;  
	    		   break;
	    	 case 3: //up
	 	    	  if(pnode.getRow()>0) {
	 	    		 pcolumn=pnode.getColumn();
	 	    		 prow=pnode.getRow()-1;
	 	    		 currentNode=mymaze[prow][pcolumn];
	 	    	  } else
	 	    		 currentNode=null;  
	    		    break;
	    		    
	    	 default:
	    		   System.out.println("error, shall not reach here");
	    		   return -1;
	    	 }
	    	 if(currentNode==null)
	    		 continue;
	    	 //skip the wall node
	    	  if(currentNode.getData()== -1)
	    		 continue;	    	
	    	  distance=currentNode.getDistance();
	    	  if(distance==0 && (!currentNode.getStartPoint())){
	    	//this is node not processed yet and it is not startpoint
	    		   currentNode.setDistance(pnode.getDistance()+1);
	    		   mazequeue.offer(currentNode);
	    	//set currentNode.preNode as pnode.
	    		   currentNode.setprevNode(pnode);
	    	  } 
	    	  else { if(distance>(pnode.getDistance()+1)){
	    				  //update to make it shorter
	    			 currentNode.setDistance(pnode.getDistance()+1);
	  	    		 mazequeue.offer(currentNode);
	  	    		currentNode.setprevNode(pnode);
	    		     } 
	    	        else { //if distance <= (pnode.getDistance()+1
	    		    	    //nothing to do	    		    	 
	    		     }	    			  
	    		  }	    			  
	    		}
	    	}
	    System.out.println("the shortest path is: "+mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].getDistance());
	    if(mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].getDistance() >0 ) {
	        //print out the shortest path from the start point.
	    	MazeNode node=mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].getprevNode();
	    	Stack<MazeNode> stack=new Stack<>();
	    	stack.push(mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1]);
	    	if(node != null) {
	    		stack.push(node);	    		
	    		node=node.getprevNode();
	    	}	    	
	    	while(node != null) {
	    		stack.push(node);
	    		node=node.getprevNode();
	    	}
	    	node=stack.pop();
	    	if(null != node)
	    		System.out.print("("+node.getRow()+","+node.getColumn()+")");
	    	while(!stack.isEmpty()) {
	    		node=stack.pop();
	    		System.out.print("->("+node.getRow()+","+node.getColumn()+")");	
	    	}
	    	
	    }
		return (distance= mymaze[MAZE_HEIGHT-1][MAZE_WIDTH-1].getDistance());
	}
}

输出结果是:

the shortest path is: 12
(0,0)->(0,1)->(1,1)->(2,1)->(2,0)->(3,0)->(4,0)->(4,1)->(4,2)->(3,2)->(3,3)->(3,4)->(4,4)

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/bigtree_3721/article/details/79836970
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞