广搜的概念不用多讲了,这里的算法主要针对二维矩阵(迷宫)的广搜。
二维矩阵中的点一般只与上下左右4个结点相邻,看题目定义,有的和斜角也相邻。所以就没必要用邻接矩阵存边数据,直接搜就可以啦。
与传统bfs不同的数据结构:
graph(二维矩阵图)
vis(二维标记,标记对应位置是否访问过)
direction(存行走方向,比如往左走就是{0,-1},表示 i 不变,j 减一嘛,同理右{0,1},上 {-1,0},下{1,0})
node(存点的位置 {x, y})
步骤不多说啦,大同小异嘛,注意队列里是存点的位置。
这里的代码主要用一个graph类来描述一个图,然后在图里面写一个深搜算法。仅作为参考。刷题的人可以只用深搜算法即可,当然要准备好对应的数据结构啦。
//此类是用来描述一个基于二维数组的图
package Graph;
import java.util.LinkedList;
public class SimpleGraph {
private static int nodeNum = 0;
private static int[][] graph;
private static int[][] direction = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
private static int[][] visited;
public SimpleGraph() {}
public SimpleGraph(int[][] graph) {
this.graph = graph;
visited = new int[graph.length][graph[0].length];
}
public int getNodeNum() {
return nodeNum;
}
//广度优先搜索Breadth First Search,从点(x, y)开始,队列实现
public void bfs(int x, int y) {
//标记数组,标记已访问的位置和已入栈的位置
int num = 0;
LinkedList queue = new LinkedList<>();
queue.add(new Node(x, y));
while (!queue.isEmpty()) {
Node tem = queue.poll();
System.out.print(graph[tem.x][tem.y] + " ");
for (int i = 0; i < direction.length; i++) {
int tx = tem.x + direction[i][0];
int ty = tem.y + direction[i][1];
//越界跳过,遇到障碍或访问过的跳过,符合条件的就入队
if (tx >= 0 && ty >= 0 && tx < graph.length && ty < graph[0].length &&
graph[tx][ty] > 0 && visited[tx][ty] == 0) {
queue.offer(new Node(tx, ty));
//防止入队过的元素重复入队
visited[tx][ty] = 1;
}
}
//标记访问过的位置
visited[tem.x][tem.y] = 1;
num++;
}
nodeNum = num;
System.out.println();
initializeVisited();
}
//初始化标记数组visited
private void initializeVisited() {
for (int i = 0; i < visited.length; i++) {
for (int j = 0; j < visited[0].length; j++)
visited[i][j] = 0;
}
}
//深度优先搜索Depth First Search,从点(x, y)开始,递归实现
public void dfs(int x, int y) {
nodeNum = 0;
dfsTrace(x, y);
System.out.println();
initializeVisited();
}
private void dfsTrace(int x, int y) {
System.out.print(graph[x][y] + " ");
//标记已遍历的结点
visited[x][y] = 1;
nodeNum++;
//从四个方向找可以走的路
for (int i = 0; i < direction.length; i++) {
int tx = x + direction[i][0];
int ty = y + direction[i][1];
//越界跳过,遇到障碍或访问过的跳过,符合条件的就递归
if (tx >= 0 && ty >= 0 && tx < graph.length && ty < graph[0].length &&
graph[tx][ty] > 0 && visited[tx][ty] == 0) {
dfsTrace(tx, ty);
}
}
}
}
class Node {
int x;
int y;
Node(int x, int y) {
this.x = x;
this.y = y;
}
}
下面是测试代码
public class TestGraph {
public static void main(String[] args) {
int[][] graph = {
{1, 4, 7, 7, 3},
{0, 2, 0, 0, 1},
{6, 7, 5, 2, 9},
{0, 6, 7, 8, 0},
{0, 5, 0, 8, 4},
};
int[][] graph2 = {
{0, 2, 9, 0, 0},
{0, 1, 0, 0, 0},
{0, 7, 5, 2, 0},
{0, 6, 7, 8, 0},
{0, 5, 0, 8, 4},
};
System.out.println("测试图的广度优先搜索");
SimpleGraph g = new SimpleGraph(graph);
g.bfs(2, 2);
System.out.println(g.getNodeNum() + "\n");
System.out.println("测试图的深度优先遍历");
SimpleGraph g2 = new SimpleGraph(graph2);
g2.dfs(2, 2);
System.out.println(g2.getNodeNum());
}
}
输出
测试图的广度优先搜索
5 2 7 7 9 8 6 2 6 1 8 5 4 3 4 7 1 7
18
测试图的深度优先遍历
5 2 8 8 4 7 6 7 1 2 9 5
12