簡體   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