广度优先算法Java实现以及最短路径搜索
广度优先算法的步骤:
1.选定一个起始节点;
2.以选定节点为中心,所有与该节点相邻节点为备选节点(其中,在之前已经访问过的节点不得再纳入相邻节点),并将这些备选节点放入一个先进先出队列中,;
3.依次取出先进先出队列中的节点,并求得该节点的相邻节点放入先进先出队列中;
4.循环进行2、3步骤;知道先进先出队列为空(搜索结束的标志);
接下来直接上java代码咯:
package Graph; import java.util.LinkedList; /***** * * 从左上角到右下角,最短路径; * 广度搜索法; * * *********/ public class BFS { /*****重要组成-方向******/ int[][] direct={{0,1},{0,-1},{-1,0},{1,0}};//四个方向,上下左右 /*****重要组成-标记******/ int[][] arc=new int[4][4];//辅助标记数组 /******输入数组*****/ int[][] array={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16} }; public static void main(String[] args) throws InterruptedException { new BFS().BFS(); } /*****重要组成-封装数组点,用坐标表示位置******/ class Node{ int row; int column; int round; Node(int row,int column,int round) { this.row=row; this.column=column; this.round=round; } } public void BFS(){//广度搜索算法 Node start=new Node(0,0,0); /*****重要组成-待搜索队列的每个对象都是接下来要所搜的值******/ LinkedList<Node> queue=new LinkedList<>();//待搜索队列 queue.offer(start); arc[0][0]=1; /*****重要组成-持续搜索的标志。待搜索队列里有东西******/ while(!queue.isEmpty()){ Node temp=queue.poll(); for(int i=0;i<4;i++){//尝试搜索四个方向的点,如果满足就加入待搜索队列中 int new_row=temp.row+direct[i][0]; int new_column=temp.column+direct[i][1]; if(new_row<0||new_column<0||new_row>=4||new_column>=4) continue;//该方向上出界,考虑下一方向 if(arc[new_row][new_column]==1)continue; arc[new_row][new_column]=1; Node next=new Node(new_row, new_column,temp.round+1); queue.offer(next); System.out.println("数值:"+array[new_row][new_column]+",轮次:"+(temp.round+1)); } } } }
运行结果:
数值:2,轮次:1 数值:5,轮次:1 数值:3,轮次:2 数值:6,轮次:2 数值:9,轮次:2 数值:4,轮次:3 数值:7,轮次:3 数值:10,轮次:3 数值:13,轮次:3 数值:8,轮次:4 数值:11,轮次:4 数值:14,轮次:4 数值:12,轮次:5 数值:15,轮次:5 数值:16,轮次:6
以上代码参考了下列博客:http://www.imooc.com/article/17187
面试题中经常会遇到,给定一个0,1矩阵,0表示可走,1表示不可走。求出从左上角到右下角的最短路径?
这里我们就可以用广度优先算法来实现(例子中给定的4*4数组):
import java.util.LinkedList; public class Main { /*****重要组成-方向******/ int[][] direct={{0,1},{0,-1},{-1,0},{1,0}};//四个方向,上下左右 /******输入数组*****/ int[][] array={ {0,0,0,0}, {0,0,1,0}, {0,0,1,0}, {0,0,1,0} }; public static void main(String[] args) throws InterruptedException { new Main().BFS(); } /*****重要组成-封装数组点,用坐标表示位置******/ class Node{ int row; int column; int round; Node pre; Node(int row,int column,int round,Node pre) { this.row=row; this.column=column; this.round=round; this.pre=pre; } } public void BFS(){//广度搜索算法 Node start=new Node(0,0,0,null); /*****重要组成-待搜索队列的每个对象都是接下来要所搜的值******/ LinkedList<Node> queue=new LinkedList<>();//待搜索队列 queue.offer(start); /*****重要组成-持续搜索的标志。待搜索队列里有东西******/ while(!queue.isEmpty()){ Node temp=queue.poll(); for(int i=0;i<4;i++){//尝试搜索四个方向的点,如果满足就加入待搜索队列中 int new_row=temp.row+direct[i][0]; int new_column=temp.column+direct[i][1]; if(new_row<0||new_column<0||new_row>=4||new_column>=4) continue;//该方向上出界,考虑下一方向 if(array[new_row][new_column]==1)continue; Node next=new Node(new_row, new_column,temp.round+1,temp); if(new_row==3&&new_column==3)//找到了出口 { queue.clear(); queue.offerFirst(next); while(next.pre!=null){ queue.offerFirst(next.pre);//以前获取父节点 next=next.pre; } for(Node node:queue) { System.out.println("("+node.row+","+node.column+"),"); } } array[new_row][new_column]=1; queue.offer(next); } } } }
执行结果:
(0,0), (0,1), (0,2), (0,3), (1,3), (2,3), (3,3),