风和日丽 2019-09-08
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
首先初始整个带权重的有向图G=(N,E).然后在将所有节点分成两个集合 S(表示已经算计完毕的节点,初始为发起节点,值为0)、U(表示未确定的节点列表,初始为 除了初始节点之外的节点,值为无限大)。按照最短路径从U里面的节点移动到S里面,必须保证U中的任意节点到原始节点的距离大于S中的任意节点到原始节点的距离。
import com.google.common.graph.ImmutableValueGraph; import com.google.common.graph.MutableValueGraph; import com.google.common.graph.ValueGraphBuilder; import lombok.extern.slf4j.Slf4j; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Optional; @Slf4j public class DijkstraTest { public static void main(String[] args) { // init MutableValueGraph<Integer, Integer> init = ValueGraphBuilder.undirected().build(); init.putEdgeValue(1, 2, 7); init.putEdgeValue(2, 3, 10); init.putEdgeValue(1, 3, 9); init.putEdgeValue(1, 6, 14); init.putEdgeValue(2, 4, 15); init.putEdgeValue(3, 6, 2); init.putEdgeValue(3, 4, 11); init.putEdgeValue(6, 5, 9); init.putEdgeValue(5, 4, 6); ImmutableValueGraph<Integer, Integer> graph = ImmutableValueGraph.copyOf(init); //1. Map<Integer, Integer> S = new HashMap<>(); Map<Integer, Integer> U = new HashMap<>(); int u = 1; S.put(1, 0); for (int i = 2; i <= 6; i++) { U.put(i, Integer.MAX_VALUE); } // 2. for (; ; ) { Integer finalU = u; graph.adjacentNodes(u).stream().filter(U::containsKey).forEach(node -> { Optional<Integer> value = graph.edgeValue(finalU, node); if (value.get() + S.get(finalU) < U.get(node)) { U.put(node, value.get()); } }); // 3. Optional<Map.Entry<Integer, Integer>> min = U.entrySet().stream().min(Comparator.comparing(Map.Entry::getValue)); u = min.get().getKey(); S.put(u, min.get().getValue()); U.remove(u); log.info("{},{}", S, U); if (U.isEmpty()) { break; } // 4. } log.info("result {}", S); } }