未加权图的最短路径(最少节点)
我正在尝试构建一种方法,该方法返回未加权图中从一个节点到另一个节点的最短路径。我考虑过使用 Dijkstra's,但这似乎有点矫枉过正,因为我只想要一对。相反,我实现了广度优先搜索,但问题是我的返回列表包含一些我不想要的节点 - 我如何修改我的代码以实现我的目标?
public List<Node> getDirections(Node start, Node finish){
List<Node> directions = new LinkedList<Node>();
Queue<Node> q = new LinkedList<Node>();
Node current = start;
q.add(current);
while(!q.isEmpty()){
current = q.remove();
directions.add(current);
if (current.equals(finish)){
break;
}else{
for(Node node : current.getOutNodes()){
if(!q.contains(node)){
q.add(node);
}
}
}
}
if (!current.equals(finish)){
System.out.println("can't reach destination");
}
return directions;
}
I'm trying build a method which returns the shortest path from one node to another in an unweighted graph. I considered the use of Dijkstra's but this seems a bit overkill since I only want one pair. Instead I have implemented a breadth-first search, but the trouble is that my returning list contains some of the nodes that I don't want - how can I modify my code to achieve my goal?
public List<Node> getDirections(Node start, Node finish){
List<Node> directions = new LinkedList<Node>();
Queue<Node> q = new LinkedList<Node>();
Node current = start;
q.add(current);
while(!q.isEmpty()){
current = q.remove();
directions.add(current);
if (current.equals(finish)){
break;
}else{
for(Node node : current.getOutNodes()){
if(!q.contains(node)){
q.add(node);
}
}
}
}
if (!current.equals(finish)){
System.out.println("can't reach destination");
}
return directions;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
实际上你的代码不会以循环图结束,考虑图 1 -> 2-> 1. 您必须有一些数组,可以在其中标记您已经访问过的节点。对于每个节点,您还可以保存您来自的先前节点。所以这是正确的代码:
Actually your code will not finish in cyclic graphs, consider graph 1 -> 2 -> 1. You must have some array where you can flag which node's you've visited already. And also for each node you can save previous nodes, from which you came. So here is correct code:
谢谢乔莱克瓦!
我重写了它,重构了一些:
Thank you Giolekva!
I rewrote it, refactoring some:
将每个节点放入队列时,必须将其父节点包括在内。然后您可以从该列表中递归读取路径。
假设您想在此图中找到从 A 到 D 的最短路径:
每次您将一个节点入队时,请跟踪您到达这里的方式。
因此,在步骤 1 中,B(A) E(A) 被放入队列中。在第二步中,B 出队,C(B) 被放入队列等。然后,只需“向后”递归,就可以轻松找到返回的路。
最好的方法可能是只要有节点就创建一个数组并将链接保留在那里(这就是 Dijkstra 中通常所做的)。
You must include the parent node to each node when you put them on your queue. Then you can just recursively read the path from that list.
Say you want to find the shortest path from A to D in this Graph:
Each time you enqueue a node, keep track of the way you got here.
So in step 1 B(A) E(A) is put on the queue. In step two B gets dequeued and C(B) is put on the queue etc. Its then easy to find your way back again, by just recursing "backwards".
Best way is probably to make an array as long as there are nodes and keep the links there, (which is whats usually done in ie. Dijkstra's).
每次通过循环时,您都会调用
相反,您应该将其移动到您真正知道需要该条目的位置。
Every time through your loop, you call
Instead, you should move that to a place where you really know you want that entry.
仅仅获得一对的答案并不比获得所有对的答案简单。计算最短路径的通常方法是像您一样开始,但是每当遇到新节点时都记下并记录路径上的前一个节点。然后,当您到达目标节点时,您可以沿着反向链接到达源并获取路径。因此,从循环中删除
directions.add(current)
,并在开头添加类似以下的代码,然后在循环中
添加代码,然后在最后,只需构造
directions< /code> 使用
backlinks
映射向后列出。It is really no simpler to get the answer for just one pair than for all the pairs. The usual way to calculate a shortest path is to start like you do, but make a note whenever you encounter a new node and record the previous node on the path. Then, when you reach the target node, you can follow the backlinks to the source and get the path. So, remove the
directions.add(current)
from the loop, and add code something like the followingin the beginning and then in the loop
and then in the end, just construct the
directions
list in backwards using thebacklinks
map.