簡體   English   中英

如何實現Dijkstra算法以找到Java中的最短路徑

[英]How to implement Dijkstra's Algorithm to find the shortest path in Java

我對做什么絕對感到困惑。 我正在嘗試從Wikipedia在Dijkstra的具有優先級隊列的偽代碼中編寫代碼,但是我很難進行調整以適應我需要找到的內容。 到目前為止,這是我的代碼(不完整),非常感謝您的幫助。

public int doDijkstras (String startVertexName, String endVertexName, ArrayList< String > shortestPath) {
        PriorityQueue<QEntry> q = new PriorityQueue<QEntry>();
        int cost = 0;
        int newCost;
        QEntry pred = null;
        for (String s : this.getVertices()) {
            if (!s.equals(startVertexName)) {
                cost = Integer.MAX_VALUE;
                pred = null;
            }
            q.add(new QEntry(s, cost, pred, adjacencyMap.get(s)));
        }

        while (!q.isEmpty()) {
            QEntry curr = getMin(q);
            for (String s : curr.adj.keySet()) {
                newCost = curr.cost + this.getCost(curr.name, s);
                QEntry v = this.getVert(q, s);
                if (newCost < v.cost) {
                    v.cost = newCost;
                    v.pred = curr;
                    if (!q.contains(curr)) {
                        q.add(curr);
                    }
                }
            }
        }
    }

    private QEntry getMin(PriorityQueue<QEntry> q) {
        QEntry min = q.peek();
        for (QEntry temp : q) {
            if (min.cost > temp.cost) {
                min = temp;
            }
        }
        return min;
    }

    private QEntry getVert(PriorityQueue<QEntry> q, String s) {
        for (QEntry temp : q) {
            if (temp.name.equals(s)) {
                return temp;
            }
        }
        return null;
    }

    class QEntry {
        String name;
        int cost;
        QEntry pred;
        TreeMap<String, Integer> adj;

        public QEntry(String name, int cost, QEntry pred, TreeMap<String, Integer> adj) {
            this.name = name;
            this.cost = cost;
            this.adj = adj;
            this.pred = pred;
        }
    }

您正在忽略算法的重要部分:何時停止。

Wikipedia上的偽代碼用於Dijkstra算法的變體,該算法計算從起始節點到與其連接的每個節點的最短路徑。 大偽代碼塊之后的注釋說明了如何修改算法以僅查找到特定目標的路徑,然后是較短的塊,說明如何提取路徑。

但是,用英語來說,在處理優先級隊列時,需要注意目標元素是否被選中。 無論何時(如果有的話),您都知道,找到它的最短路徑就是將成本記錄在目標隊列條目中並由該條目及其前身鏈(以相反順序)表示的路徑。 通過遍歷前輩鏈來填充路徑列表,然后返回目標隊列條目中記錄的值。

但是請注意,在您的代碼中,如果起始頂點和目標頂點未在圖中連接(包括目標根本不在圖中),最終將耗盡隊列並跌出底部。而while循環卻從未達到目標。 您必須決定如何處理路徑列表以及在這種情況下要返回什么。

還要注意,您的代碼似乎有幾個錯誤,其中包括:

  • 如果起始頂點名稱不是this.getVertices()的迭代順序中的第一個,則其隊列條目將不會使用成本0進行初始化,並且不可能是從隊列中選擇的第一個元素。
  • 如果指定的起始頂點根本不在圖形中,則您的代碼將運行,並可能發出路徑,但在這種情況下其輸出是虛假的。
  • 您的隊列元素(類型QEntry )沒有自然順序。 要創建其元素具有此類的PriorityQueue ,必須提供一個Comparator來定義其相對優先級。
  • 您將優先級隊列用作普通列表。 這本身不會使您的代碼產生錯誤的結果,但是增加其漸近復雜性。
  • 但是請注意,如果將標准PriorityQueue 用作優先級隊列,則絕不能以可能改變其相對於任何其他排隊對象順序的方式修改排隊對象。 而是先將其從隊列中刪除,然后對其進行修改,然后再次使其入隊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM