廣度優先算法
基本思想
它的思想是從一個頂點V0開始,輻射狀地優先遍歷其周圍較廣的區域。搜索過程:先訪問節點v;再依次訪問與v相鄰的節點;訪問這些節點之後,再訪問與之相鄰的節點。與深度優先搜索不同,其先遍歷周圍的是周圍節點。常用於尋找最短路徑的解決方案。
基本模型(通過隊列完成)
起始點入隊; while(隊列不爲空) { 頭結點出隊; for(遍歷周圍的子節點) { 若它是所求的目標狀態, 跳出循環; 否則, 將隊頭節點的所有子結點全都入隊; } }
算法的關鍵在於先將起始點入隊,然後遍歷周圍的節點,已廣度爲第一優先級,所以通過廣度優先算法最先找到的一定是路徑最短的那個。
一個王子拯救公主的故事
小時候大家肯定都玩過迷宮遊戲,遊戲的大概就是在迷宮中找一條繞過阻礙的路線到達公主所在的地方拯救公主。大概就像這樣(圖畫的比較挫,不過很能表達意思:):
王子從(0,0)出發尋找公主,中間要繞過障礙物,找到最近的到達公主的路線長,這裏就可以通過廣度優先算法來實現。
代碼實現
public class Bfs { public static int p=3; public static int q=2; public static int direct[][]={{1,0},{0,1},{-1,0},{0,-1}}; //下一步的方向 public static boolean book_maze[][]=new boolean[5][4]; public static int maze[][]=new int[5][4]; public static class Step{ public int x; public int y; public int count; //已經經過的步數 public Step(int x, int y, int count) { super(); this.x = x; this.y = y; this.count = count; } } @Test public void bfs(){ maze[0][2]=1; maze[2][2]=1; maze[3][1]=1; maze[4][3]=1; //初始化迷宮 Queue<Step> queue=new LinkedList<>(); Step step1=new Step(0,0,0); queue.offer(step1); while(!queue.isEmpty()){ Step temp=queue.poll(); for(int i=0;i<3;i++){ int tx=temp.x+direct[i][0]; int ty=temp.y+direct[i][1]; if(tx==p&&ty==q){ System.out.println("success:"+temp.count); //找到即爲最短路徑 return; } if(tx>4||tx<0||ty>3||ty<0){ continue; } if(maze[tx][ty]!=1&&book_maze[tx][ty]!=true){ book_maze[tx][ty]=true; queue.offer(new Step(tx,ty,temp.count+1)); } } } } }
- 代碼中首先將第一個step(即王子的出發路徑)入隊。
- 然後遍歷step1周圍的路,如果能走的,則加入隊列,如果不能走則放棄,不加入隊列。
- 不斷循環直到隊列爲空或者已經找到公主爲止。
同樣,我們也可以使用深度優先算法成功找到拯救公主的最短路線。
public static int p=3; public static int q=2; public static int mini=9999; public static int direct[][]={{1,0},{0,1},{-1,0},{0,-1}}; public static boolean book_maze[][]=new boolean[5][4]; public static int maze[][]=new int[5][4]; public static void maze(int x,int y,int step){ if(x==p&&y==q){ if(step<mini){ mini=step; } return ; } for(int i=0;i<3;i++){ int tx=x+direct[i][0]; int ty=y+direct[i][1]; if(tx>4||tx<0||ty>3||ty<0){ continue; } if(maze[tx][ty]==0&&book_maze[tx][ty]==false){ book_maze[tx][ty]=true; maze(tx,ty,step+1); book_maze[tx][ty]=false; } } } @Test public void testMaze(){ maze[0][2]=1; maze[2][2]=1; maze[3][1]=1; maze[4][3]=1; maze(0,0,0); System.out.println(mini); }
由於DFS最先找到的路徑並不一定就是最小的,所以通過引入變量mini,每次找到路徑就將其與mini比較,如果mini比找到的大,則將mini更新爲剛找到的路徑長度。