繁体   English   中英

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

[英]Finding shortest path between two nodes

我试图弄清楚如何制作一种在两个节点之间找到最短路径的方法,但似乎无法弄清楚。 我得到了两个文件,一个包含演员(将是节点)的文件和一个包含电影(将是边缘)的文件。

我将一个图表表示为一个 HashMap,其中键是一个演员,而值是一个 ArrayList,其中包含该演员出演过的电影:

HashMap<Actor, ArrayList[Movie]> graph;

现在我想找到两个演员之间的最短路径,但我不知道该怎么做。 我在考虑 DFS 或 BFS,但我不太确定如何使用这个哈希图来做到这一点..

可以使用您当前的结构( HashMap<Actor, ArrayList<Movie>> )作为邻接列表,但缺少一些东西:一种从电影回到主演的有效方法。 您可以构建一个Map<Movie, List<Actor>> ,这会起作用……但使用单个邻接列表更简单,而不是让一个用于演员而另一个用于电影。 我会这样做(假设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);
     }
 }

现在您可以使用edges来执行标准的广度优先搜索。 保证为您提供任意 2 个演员之间的最短路径(可能有多个同样短的路径),并且该路径将包含链接他们的电影。

仅仅为您指明方向并不是整个解决方案,您必须按照tucuxi 建议创建一个 Map<Movie, List> 。 您一个一个地遍历每个角色并标记当前角色与参考角色的距离。

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);
}

我在这里使用ArrayDeque以 BFS 方式遍历,如果您希望 DFS 记住,计算距离的逻辑也需要更改,您可以修改。 从评论中粘贴图像,将节点 B 作为参考参与者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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