1. 程式人生 > 其它 >Java實現單源最短路徑演算法(Dijkstra 演算法)

Java實現單源最短路徑演算法(Dijkstra 演算法)

參考:《演算法導論》

@Data
@AllArgsConstructor
public class WeightGraph {
    //節點名,前驅節點,最短路徑
    private List<Node<String,String,Integer>> nodes;
    //節點名,連線節點索引,邊權重
    private Table<String, Integer, Integer> edgeTable;


    public static void main(String[] args) {
        //構建圖
        WeightGraph graph = buildGraph();
        List
<Node<String, String, Integer>> nodes = graph.getNodes(); Table<String, Integer, Integer> edgeTable = graph.getEdgeTable(); //已知最短路徑的節點集合S HashSet<String> S = new HashSet<>(); //優先佇列,以最短路徑為排序key Queue<Node<String,String, Integer>> queue = new
PriorityQueue<>(Comparator.comparing(Node::getDistance)); //節點資訊的初始化,v1=0,其他未知都是無窮大 nodes.forEach(node->{ if (node.getName().equals("v1")) { node.setDistance(0); } }); //佇列初始化,將所有節點加入佇列 queue.addAll(nodes); while
(!queue.isEmpty()) { //第一個獲取的就是v1 Node<String,String, Integer> nodeU = queue.remove(); String nodeUName = nodeU.getName(); S.add(nodeUName); Map<Integer, Integer> row = edgeTable.row(nodeUName); //對u->v節點進行鬆弛操作 //如果v.d大於u.d+w(u,v),則將更小的值更新為v.d for (Map.Entry<Integer, Integer> entry : row.entrySet()) { Integer nodeVIndex = entry.getKey(); Node<String, String, Integer> nodeV = nodes.get(nodeVIndex); Integer weightUV = entry.getValue(); if (nodeV.getDistance() > nodeU.getDistance() + weightUV) { nodeV.setDistance(nodeU.getDistance() + weightUV); nodeV.setPre(nodeUName); } } } for (Node<String, String, Integer> node : nodes) { System.out.println(node.getName()+":"+node.getDistance()); } System.out.println(S); } /** * 初始化圖結構 * * @return */ public static WeightGraph buildGraph() { List<String> nodes = Lists.newArrayList("v1", "v2", "v3", "v4", "v5", "v6"); List<Node<String, String, Integer>> nodeList = nodes.stream().map(node -> { Node<String, String, Integer> nodeObj = new Node<>(); nodeObj.setName(node); nodeObj.setPre(null); nodeObj.setDistance(Integer.MAX_VALUE); return nodeObj; }).collect(Collectors.toList()); Table<String, Integer, Integer> edgeTable = HashBasedTable.create(); edgeTable.put("v1", nodes.indexOf("v2"), 10); edgeTable.put("v2", nodes.indexOf("v3"), 7); edgeTable.put("v4", nodes.indexOf("v3"), 4); edgeTable.put("v4", nodes.indexOf("v5"), 7); edgeTable.put("v6", nodes.indexOf("v5"), 1); edgeTable.put("v1", nodes.indexOf("v6"), 3); edgeTable.put("v6", nodes.indexOf("v2"), 2); edgeTable.put("v4", nodes.indexOf("v1"), 3); edgeTable.put("v2", nodes.indexOf("v4"), 5); edgeTable.put("v6", nodes.indexOf("v4"), 6); return new WeightGraph(nodeList,edgeTable); } /** * 節點名,前驅節點,最短路徑 * 也用於儲存最終的最短路徑資料 * * @param <N> * @param <D> */ @Data @AllArgsConstructor @NoArgsConstructor static class Node<N,P, D> { private N name; private P pre; private D distance; } }

輸出:

v1:0
v2:5
v3:12
v4:9
v5:4
v6:3