广度优先算法
基本思想
它的思想是从一个顶点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更新为刚找到的路径长度。