[英]Finding shortest path between two nodes
I am trying to figure out how to make a method which finds the shortest way between two nodes, but cant seem to figure it out.我试图弄清楚如何制作一种在两个节点之间找到最短路径的方法,但似乎无法弄清楚。 I was given two files, one file containing actors (which will be the nodes) and one with movies (which will be the edges).
我得到了两个文件,一个包含演员(将是节点)的文件和一个包含电影(将是边缘)的文件。
I have represented a graph as a HashMap where the key is a actor, and the value is a ArrayList with the movies that actor has played in:我将一个图表表示为一个 HashMap,其中键是一个演员,而值是一个 ArrayList,其中包含该演员出演过的电影:
HashMap<Actor, ArrayList[Movie]> graph;
Now i wanna find the shortest way between two actors but i dont know how to.现在我想找到两个演员之间的最短路径,但我不知道该怎么做。 I was thinking DFS or BFS but im not quite sure how to do that with this hashmap..
我在考虑 DFS 或 BFS,但我不太确定如何使用这个哈希图来做到这一点..
You can use your current structure ( HashMap<Actor, ArrayList<Movie>>
) as an adjacency list, but there is something missing: an efficient way to go from movies back to actors that starred in them.您可以使用您当前的结构(
HashMap<Actor, ArrayList<Movie>>
)作为邻接列表,但缺少一些东西:一种从电影回到主演的有效方法。 You can build a Map<Movie, List<Actor>>
, and that would work... but it is simpler to use a single adjacency list, instead of having one for actors and another for movies.您可以构建一个
Map<Movie, List<Actor>>
,这会起作用……但使用单个邻接列表更简单,而不是让一个用于演员而另一个用于电影。 I would do as follows (assuming that Actor
and Movie
both have equals
and hashcode
implemented, and no actor equals any movie):我会这样做(假设
Actor
和Movie
都实现了equals
和hashcode
,并且没有演员等于任何电影):
Map<Object, List<Object>> edges = new HashMap<>();
for (Map.Entry<Actor, ArrayList<Movie>> e : graph.entries()) {
Actor a = e.getKey();
edges.put(a, new ArrayList<Object>(e.getValues()));
for (Movie m : e.getValues()) {
List<Actor> otherActors = edges.getOrDefault(m, new ArrayList<Object>());
otherActors.add(a);
edges.put(m, otherActors);
}
}
Now you can use edges
to perform a standard breadth-first search.现在您可以使用
edges
来执行标准的广度优先搜索。 It is guaranteed to give you a shortest path (there may be multiple equally-short paths) between any 2 actors, and the path will contain the movies that link them.保证为您提供任意 2 个演员之间的最短路径(可能有多个同样短的路径),并且该路径将包含链接他们的电影。
It's not the entire solution just to point you in the direction, you will have to create a Map<Movie, List> as tucuxi suggested .仅仅为您指明方向并不是整个解决方案,您必须按照tucuxi 建议创建一个 Map<Movie, List> 。 You traverse every actor one by one and mark the distance on the current actor from your reference actor.
您一个一个地遍历每个角色并标记当前角色与参考角色的距离。
private static void fn(HashMap<Actor, List<Movie>> graph, Actor referenceActor) {
var movieMap = new HashMap<Movie, List<Actor>>();
graph.forEach((key, value) -> {
for (var movie : value) {
movieMap.compute(movie, (k, v) -> {
if (v == null) {
return new ArrayList<>(List.of(key));
}
v.add(key);
return v;
});
}
});
final var visited = new HashSet<Actor>();
var dq = new ArrayDeque<Actor>();
var map = new HashMap<Actor, Integer>();
dq.add(referenceActor);
int distance = 0;
while (!dq.isEmpty()) {
var size = dq.size();
for (int i = 0; i < size; i++) {
var actor = dq.poll();
visited.add(actor);
map.putIfAbsent(actor, distance);
for (Movie movie : graph.get(actor)) {
// adding every non visited actor in the same movie in the queue
dq.addAll(movieMap
.get(movie)
.stream()
.filter(x -> !visited.contains(x))
.collect(Collectors.toList()));
}
}
distance++;
}
System.out.println(map);
}
I used ArrayDeque
here to traverse in BFS fashion you can mend if you want DFS bear in mind the logic to calculate distance will also need to be changed.我在这里使用
ArrayDeque
以 BFS 方式遍历,如果您希望 DFS 记住,计算距离的逻辑也需要更改,您可以修改。 Pasting the image from the comments , taking node B as reference actor.从评论中粘贴图像,将节点 B 作为参考参与者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.