基本步骤:
1.从图中某个顶点v0出发,首先访问v0;
2.依次访问v0的各个未被访问的邻接点;
3.依次从上述邻接点出发,访问它们的各个未被访问的邻接点。
4.若此时图中仍有未被访问的结点,则另选图中的一个未被访问的顶点作为起始点。重复广度优先搜索过程,直到图中的所有节点均被访问过。
基本代码结构
通常用队列(先进先出,FIFO)实现
初始化队列Q.
Q={起点s};
标记s为己访问;
while (Q非空) {
取Q队首元素u; u出队;
if (u == 目标状态) {…}
所有与u相邻且未被访问的点进入队列;
标记与u相邻的点为已访问;
}
图解
效率分析
例题:使用广度优先搜索解决矩阵迷宫问题
步骤
- 初始化队列,根据题目的要求使用相关的要求
1.1 初始化一个队列进行出队和入队邻节点
1.2 使用节点类进行存储一个节点的前后节点,节点我设置双向,可以左右遍历(可以使用数组)
1.3 使用List存储相关的节点(可以使用其他的)
1.4 使用数组存储走过的路径(也可以使用自身的位置改变) - 入队第一个节点,在while循环内遍历所有节点
2.1 先出队节点,将节点存储到List中
2.2 判断当前节点是否到了目标点
2.3 开始循环下上下左右节点,根据条件存入队列中,节点自身标记上一个节点是谁 - 取出List列表的末尾节点,根据节点,编序前序节点即可
public void breadthFirstSearch(int[][] maze){
//没有参数的情况
int[][] map ={/*y*/
/* x*/{0, 1, 0, 0, 0, 0} ,
{0, 1, 0, 1, 1, 0},
{0, 0, 0, 0, 1, 0},
{0 ,1, 1, 0, 1, 0},
{1 ,0, 1, 0, 1, 0},
{1 ,0, 0, 0, 1, 0}
};
int m=map.length;
int n= map[0].length;
//---------------------------------
int[] dirx = {0,0,-1,1};
int[] diry = {-1,1,0,0};// 上下左右
int[][] visited=new int[m][n]; //用来记录是否访问过
Node start=new Node(0,0);
Queue<Node> queue=new LinkedList<Node>();
ArrayList<Node> arrayList=new ArrayList<Node>();// 用来保存每一个出队列的节点
queue.offer(start);
//第二步
while (!queue.isEmpty()){
Node local=queue.remove();//取出当前的节点
arrayList.add(local);//先加入节点
//如果上次也入队列的节点已经是最后的,则退出
if (local.x==m-1&&local.y==n-1){
break;
}
for (int i=0;i<4;i++){
//循环4次,上下左右
Node nbr=new Node(local.x+dirx[i],local.y+diry[i]);
if(nbr.x>=0&&nbr.x<m&&nbr.y>=0&&nbr.y<n //边界条件
&&map[nbr.x][nbr.y]==0 //下一节点等于0
&&visited[nbr.x][nbr.y]==0
){
visited[nbr.x][nbr.y]=1;//记录当前的节点
queue.offer(nbr);//入栈
nbr.prex=local.x;// 保存前驱节点
nbr.prey=local.y;// 保存前驱节点
}//if
} //for
}
//下面使为了方便输出,去除不能联连通的节点 下面的m-1和n-1是寻找的点
if(arrayList.get(arrayList.size()-1).x!=m-1||arrayList.get(arrayList.size()-1).y!=n-1){// 找到起始节点就停止
System.out.println("没有找找路径");
return;
}
//第三步,为了输出而已
Stack<Integer> stack=new Stack<Integer>();
int px=arrayList.get(arrayList.size()-1).prex;// 获得目的节点的前驱节点
int py=arrayList.get(arrayList.size()-1).prey;
stack.push(arrayList.size()-1);// 将目的节点在arrayList中的位置记录下来,便于输出
while (true){
if(px==0&&py==0){// 找到起始节点就停止
break;
}
for(int i=0;i<arrayList.size();i++){// 循环找出每一个节点的前驱,找到就跳出当前循环
if(arrayList.get(i).x==px&&arrayList.get(i).y==py){
px=arrayList.get(i).prex;
py=arrayList.get(i).prey;
stack.push(i);// 保存节点在arrayList中的位置
break;
}
}
}
System.out.println("(0,0)");
while (!stack.isEmpty()){
System.out.println("("+arrayList.get(stack.peek()).x+","+arrayList.get(stack.peek()).y+")");
stack.pop();
}
}
class Node{
int x;
int y;
int prex;// 保存前驱节点位置
int prey;
Node(int x,int y){
this.x=x;
this.y=y;
}
}