廣度優先算法的步驟:
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),
