用广度优先搜索解决迷宫问题
我们如何才能找到从A点到B点的最快方法?解决这样的问题在计算中非常常见。视频游戏中的敌方AI需要能够找到通往玩家的最快途径。谷歌地图需要找到到达目的地的最快方法。在这里,我们只是想解决一个迷宫。
有 几种 寻路 算法。我们今天要关注的是广度优先搜索或BFS。这种算法可以保证在未加权的图上给出最快的路径。
什么是图?

这是个图。与树不同,图被允许有循环引用。图中的每一个点都被称为一个顶点。连接顶点的线被称为边。
有些图可能是加权的,这意味着有些边比其他边长。有些边可能是有方向的,比如说,连接只能朝一个方向走。

我们将专注于非加权图,因为BFS在其他方面不是很有用。BFS可以在有向图上工作,但如何做到这一点,将留给读者一个练习。
创建一个哈希图
我们需要能够在计算机的内存中存储图形。每个顶点可以简单地表示为其邻居的列表。
// in case you can't tell, these examples are using Java
class Vertex {
private LinkedList<Vertex> adjacents;
public Vertex() {
this.adjacents = new LinkedList<>();
}
public void addAdjacent(Vertex adjacentVertex) {
adjacents.add(adjacentVertex);
}
public LinkedList<Vertex> getAdjacents() {
return this.adjacents;
}
// you probably want to override the hash() function
}
图可以是一个HashMap,包含每个顶点的名称和顶点。如果你不知道什么是HashMap,你可能想看一下这篇文章。
class Graph {
private HashMap<String, Vertex> vertices;
public Graph() {
this.vertices = new HashMap<>();
}
public Vertex addVertex(String name) {
Vertex vertex = new Vertex();
vertices.put(name, vertex);
return vertex;
}
public void addEdge(String vertex1, String vertex2) {
Vertex v1 = vertices.get(vertex1);
Vertex v2 = vertices.get(vertex2);
v1.addAdjacent(v2);
v2.addAdjacent(v1);
}
}
遍历图
我们需要一个要遍历的顶点队列。每当我们到达某个顶点时,我们就将其所有相邻的顶点添加到队列中,除非该顶点已经被到达。我们需要一个HashSet来存储我们已经到达的顶点。我们将制作一个breadthFirstTraversal 方法,其中包含以下内容。
public void breadthFirstTraversal(String start, String end) {
Vertex startVert = vertices.get(start);
Vertex endVert = vertices.get(end);
LinkedList<Vertex> queue = new LinkedList<>(); // LinkedList implements Queue
HashSet<Vertex> visited = new HashSet<>();
visited.add(startVert); // this is the first vertex
Vertex current = startVert; // the current vertex to check
while (current != endVert) { // repeats until the end is reached
LinkedList<Vertex> adjacents = current.getAdjacents(); // get adjacents
for (Vertex v: adjacents) { // add all the adjacents
if (!visited.contains(v)) { // but only if it hasn't already been traversed
visited.add(v);
queue.add(v);
}
}
current = queue.remove(); // goes to the next vertex
}
}
创建一个路径
当然,这个算法所做的就是遍历图形。我们需要一个路径。幸运的是,这出乎意料的简单。对于每个顶点,我们都需要存储前一个顶点。我们可以把HashSet改成HashMap来做这件事。我们需要一个路径的顶点列表。我们将从添加最后一个顶点的前一个顶点开始,然后是它的前一个顶点,以此类推,直到我们到达起点。
public LinkedList<Vertex> breadthFirstSearch(String start, String end) {
Vertex startVert = vertices.get(start);
Vertex endVert = vertices.get(end);
LinkedList<Vertex> queue = new LinkedList<>(); // LinkedList implements Queue
HashMap<Vertex, Vertex> visited = new HashMap<>();
visited.put(startVert, null); // this is the first vertex
Vertex current = startVert; // the current vertex to check
while (current != endVert) { // repeats until the end is reached
LinkedList<Vertex> adjacents = current.getAdjacents(); // get adjacents
for (Vertex v: adjacents) { // add all the adjacents
if (!visited.containsKey(v)) { // but only if it hasn't already been traversed
visited.put(v, current);
queue.add(v);
}
}
current = queue.remove(); // goes to the next vertex
}
// create the path
LinkedList<Vertex> path = new LinkedList<>();
path.addFirst(current);
while (current != startVert) {
current = visited.get(current);
path.addFirst(current); // addFirst is used to get the correct order
}
return path;
}
接下来的几张图片展示了这段代码的具体运作。





解决迷宫的问题
如果你想知道,用这个方法解决迷宫,你所需要做的就是把它变成一个图形
