Dijkstra 算法解決有向圖單源最短路徑問題,以起點為中心向外層層擴展。本文提供介面定義、數據結構設計、核心遞歸邏輯、路徑回溯組裝、完整可運行代碼與測試用例。
// 返回結果
public class MinStep {
private boolean reachable;
private int minStep;
private List path; // 起點→終點節點序列
}
// 算法過程中每個節點的最優前驅與距離
public class PreNode {
private int preNode; // 最短路徑下的前一個節點
private int nodeStep; // 起點到該節點的最短距離
}
private Map> graph; // 輸入圖 private int nodeCount; // 節點總數 private Set visited; // 已確定最短路徑的節點 private Map shortest; // 節點→{前驅,距離} private Deque frontier; // 待處理節點隊列 private int start, end; // 起終點
step()private MinStep buildResult() {
MinStep ms = new MinStep();
ms.setReachable(true);
ms.setMinStep(shortest.get(end).nodeStep);
LinkedList path = new LinkedList<>();
int cur = end;
path.addFirst(cur);
while (shortest.containsKey(cur)) {
cur = shortest.get(cur).preNode;
path.addFirst(cur);
}
ms.setPath(path);
return ms;
}
DistanceDijkstraImplpublic class DistanceDijkstraImpl implements Distance {
public MinStep getMinStep(int start, int end, Map> graph) {
this.graph = graph;
this.nodeCount = graph != null ? graph.size() : 0;
if (graph == null || !graph.containsKey(start) || !graph.containsKey(end)) {
return MinStep.UNREACHABLE;
}
init(start, end);
step();
return shortest.containsKey(end) ? buildResult() : MinStep.UNREACHABLE;
}
// ... init/step/buildResult 如上
}
public class DijkstraTest {
public static void main(String[] args) {
Map> g = new HashMap<>();
// 1→2(7) 1→3(9) 1→6(14)
put(g, 1, 2, 7); put(g, 1, 3, 9); put(g, 1, 6, 14);
// 2→1(7) 2→3(10) 2→4(15)
put(g, 2, 1, 7); put(g, 2, 3, 10); put(g, 2, 4, 15);
// 3→1(9) 3→2(10) 3→4(11) 3→6(2)
put(g, 3, 1, 9); put(g, 3, 2, 10); put(g, 3, 4, 11); put(g, 3, 6, 2);
// 4→2(15) 4→3(11) 4→5(5)
put(g, 4, 2, 15); put(g, 4, 3, 11); put(g, 4, 5, 5);
// 5→4(5) 5→6(9)
put(g, 5, 4, 5); put(g, 5, 6, 9);
// 6→1(14) 6→3(2) 6→5(9)
put(g, 6, 1, 14); put(g, 6, 3, 2); put(g, 6, 5, 9);
Distance dijkstra = new DistanceDijkstraImpl();
MinStep result = dijkstra.getMinStep(1, 5, g);
System.out.println(result); // {reachable=true, minStep=20, path=[1, 3, 6, 5]}
}
static void put(Map> g, int u, int v, int w) {
g.computeIfAbsent(u, k -> new HashMap<>()).put(v, w);
}
}
{reachable=true, minStep=20, path=[1, 3, 6, 5]}
路徑 1→3(9) → 6(2) → 5(9) = 20,符合教科書標準答案。