简体   繁体   English

寻找两个节点之间的最短路径

[英]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):我会这样做(假设ActorMovie都实现了equalshashcode ,并且没有演员等于任何电影):

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM