实现图的 BFS 搜索方法
我正在实现我自己的图形类。我的无向图由一个映射表示,该映射将每个节点映射到存储其具有的边的列表。
private Map<T, List<Edge<T>>> graphRep = new HashMap<>();
private static class Edge<T> {
int cost;
T node;
public Edge(T n, int w) {
node = n;
cost = w;
}
我已经为我的图创建了一个递归深度优先遍历方法,它利用映射来存储起始节点到搜索节点之间的路径。它通过将起始节点到结束节点之间的路径上的每个节点映射到下一个节点来实现。
@Override
public List<T> depthFirstSearch(T start, T end) {
Set<T> visited = new HashSet<T>();
Map<T,T> path = new HashMap<>();
recursiveDFS(start, end, visited,path);
List<T> myList = new ArrayList<T>();
T current = end;
myList.add(current);
while (current != start) {
myList.add(path.get(current));
current = path.get(current);
}
System.out.println(path);
System.out.println(myList);
Collections.reverse(myList);
return myList;
}
private void recursiveDFS (T node, T end, Set<T> visited, Map<T, T> path) {
// uppdatera path och visited
visited.add(node);
for (Edge<T> e : graphRep.get(node)) {
if (e.node == end) {
path.put(e.node, node);
return;
}
if (!visited.contains(e.node)){
path.put(e.node, node);
recursiveDFS(e.node, end, visited, path);
}
}
}
我相信我可以使用与深度优先搜索基本相同的代码进行广度优先搜索,只是不是按深度遍历节点,而是按广度遍历节点,这就是我陷入困境的地方。我完全不知道该怎么做。
@Override
public List<T> breadthFirstSearch(T start, T end) {
Set<T> visited = new HashSet<T>();
Map<T,T> path = new HashMap<>();
recursiveBFS(start, end, visited,path);
List<T> myList = new ArrayList<T>();
T current = end;
myList.add(current);
while (current != start) {
myList.add(path.get(current));
current = path.get(current);
}
System.out.println(path);
System.out.println(myList);
Collections.reverse(myList);
return myList;
}
public void recursiveBFS (T node, T end, Set<T> visited, Map<T, T> path) {
visited.add(node);
for (Edge<T> e : graphRep.get(node)) {
if (e.node == end) {
path.put(e.node, node);
return;
}
if (!visited.contains(node)) {
//Here's where I'm stuck. I have no idea how to traverse the graph by breadth
}
}
}
如何完成我的广度优先遍历方法?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
BFS 需要一个允许按照访问顺序检索节点的容器。它无法通过
Map
实现。为此,您需要一个Queue
(仔细查看说明这个算法的)。注意,虽然 BFS 可以递归实现,但迭代方法更适合此任务。
首先,您需要创建一个队列并添加一个起始节点进入其中。然后队列将作为参数传递给
recursiveBFS()
。每次调用
recursiveBFS()
时,队列开头的节点都会被删除。如果队列为空,则意味着起始节点和结束节点未连接。这就是递归实现的样子:
为了使该解决方案遵守 Single责任原则我从
breadthFirstSearch()
到单独的方法中。建议:
Vertex
类添加到您的图,那么将包含引用边的集合,那么您可以仅使用实现图遍历算法>边和顶点,无需依赖graphRep
。==
进行比较,而是使用equals()
方法。e
这样的单字母变量。myList
这样命名,而是尝试使用能够解释此变量用途的名称(例如path
)。更新
下面是 BFS 的迭代实现:
如果考虑上面的建议,迭代解决方案会更清晰。由于对于BFS以及DFS,我们不需要任何特定于边的信息(因为顶点 (节点)可以存储有关调整顶点的数据)这些算法只能使用顶点来实现。
BFS requires a container that will allow to retrieve nodes in the order they were visited. It can't be achieved with a
Map
. You need aQueue
for that purpose (take a look carefully at the description of this algorithm).Note that although BFS could be implemented recursively, the iterative approach is way better for this task.
Firstly, you need to create a queue and add a starting node into it. Then the queue will be passed as an argument to the
recursiveBFS()
.At each call of the
recursiveBFS()
a node at the beginning of the queue will be removed. If the queue is empty that will mean that the start-node and end-node are not connected.That is how recursive implementation might look like:
In order to make this solution adhere to the Single responsibility principle I extracted the logic for restoring the path from the start-node to end-node from the
breadthFirstSearch()
into the separate method.Recommendations:
Map<T, List<Edge<T>>> graphRep
, edges are helpless without it. You might consider refining your graph so that its elements will be more self-contained. Firstly, in my opinion, the edge of a graph has to have two references because by definition it is meant to represent a connection between two vertices of the graph. And if you add aVertex
class to your graph then will contain reference a collection of edges then you can implement graph traversal algorithms using only edges and vertexes without a need to fall back ongraphRep
.==
, useequals()
method instead.e
.myList
, but try to come up with the name that explains the purpose of this variable (likepath
).Update
Below is an iterative implementation of BFS:
An iterative solution would be cleaner if you take into account recommendation above. And since for BFS as well as for DFS we don't need any information specific to edges (because vertex (node) can store data about adjusent vertexes) these algorithms could be implemented using vertecies only.