[英]Undirected graph for k shortest paths in Dijkstra using Java
I'm trying to implement Dijkstra algorithm to calculate k-shortest paths in java so far here is the code i'm using:到目前为止,我正在尝试实现 Dijkstra 算法来计算 Java 中的 k 最短路径,这是我正在使用的代码:
import java.util.List;
public interface AbstractKShortestPathFinder<V> {
List<Path<V>> findShortestPaths(V source, V target, Graph<V> graph, int `k);`
default void checkK(int k) {
if (k < 1) {
throw new IllegalArgumentException(
String.format("The value of k is too small: %d, should `be at least 1.", k));`
}
}
}
- ——
import java.util.*;
import static java.util.Objects.requireNonNull;
public class DefaultKShortestPathFinder<V> implements AbstractKShortestPathFinder<V> {
@Override
public List<Path<V>> findShortestPaths(V source, V target, Graph<V> graph, int k) {
requireNonNull(source, "The source node is null.");
requireNonNull(target, "The target node is null.");
requireNonNull(graph, "The graph is null.");
checkK(k);
List<Path<V>> paths = new ArrayList<>(k);
Map<V, Integer> countMap = new HashMap<>();
Queue<Path<V>> HEAP = new PriorityQueue<>(
Comparator.comparingDouble(Path::pathCost));
HEAP.add(new Path<>(source));
while (!HEAP.isEmpty() && countMap.getOrDefault(target, 0) < k) {
Path<V> currentPath = HEAP.remove();
V endNode = currentPath.getEndNode();
countMap.put(endNode, countMap.getOrDefault(endNode, 0) + 1);
if (endNode.equals(target)) {
paths.add(currentPath);
}
if (countMap.get(endNode) <= k) {
for (Edge<V> edge : graph.get(endNode)) {
Path<V> path = currentPath.append(edge);
HEAP.add(path);
}
}
}
return paths;
}
}
- ——
public class Edge<V> {
public final V from;
public final V to;
public final double weight;
public Edge(V from, V to, double weight) {
this.from = from;
this.to = to;
this.weight = weight;
if (Double.isNaN(weight)) {
throw new IllegalArgumentException("The weight is NaN.");
}
if (weight < 0.0) {
throw new IllegalArgumentException("The weight is negative.");
}
}
}
- ——
import java.util.*;
import static java.lang.String.*;
public class Graph<V> {
//could be replaced by http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Table.html
private Map<V,Map<V,Edge<V>>> vertexEdgeMap = new HashMap<>();
@SafeVarargs
public Graph(Edge<V> ... edges) {
for (Edge<V> edge : edges) {
addEdge(edge);
}
}
private void addEdge(Edge<V> edge) {
vertexEdgeMap.putIfAbsent(edge.from, new HashMap<>());
Map<V, Edge<V>> fromMap = vertexEdgeMap.get(edge.from);
if(fromMap.containsKey(edge.to)) {
throw new IllegalArgumentException(format("Edge between %s and %s was added twice", edge.from, edge.to));
}
fromMap.put(edge.to, edge);
}
public Edge<V> get(V from, V to) {
return vertexEdgeMap.get(from).get(to);
}
public Collection<Edge<V>> get(V from) {
return vertexEdgeMap.getOrDefault(from, Collections.emptyMap()).values();
}
}
- ——
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static java.lang.String.format;
public class Path<V> {
private final V node;
private final double totalCost;
public Path(V source) {
Objects.requireNonNull(source, "The input source node is null.");
node = source;
totalCost = 0.0;
}
private Path(V node, double totalCost) {
this.node = node;
this.totalCost = totalCost;
}
public Path<V> append(Edge<V> edge) {
if (!node.equals(edge.from)) {
throw new IllegalArgumentException(format("The edge %s doesn't extend the path %s", edge, this.getNodeList()));
}
return new NonEmptyPath<>(this, edge);
}
public V getEndNode() {
return node;
}
public List<V> getNodeList() {
return new ArrayList<>();
}
public double pathCost() {
return totalCost;
}
private static class NonEmptyPath<V> extends Path<V> {
private final Path<V> predecessor;
public NonEmptyPath(Path<V> path, Edge<V> edge) {
super(edge.to, path.totalCost + edge.weight);
predecessor = path;
}
@Override
public List<V> getNodeList() {
LinkedList<V> result = new LinkedList<>();
Path<V> path = this;
while(path instanceof NonEmptyPath) {
result.addFirst(path.node);
path = ((NonEmptyPath<V>) path).predecessor;
}
result.addFirst(path.node);
return result;
}
@Override
public String toString() {
return getNodeList().toString();
}
}
}
- ——
import java.util.List;
public class Execution {
public static void main(String[] args) {
execution();
}
private static void execution() {
Graph<Character> graph = new Graph<>(
// new Edge<>('a', 'b', 5.0),
new Edge<>('a', 'c', 3.0),
new Edge<>('b', 'c', 2.0),
new Edge<>('b', 'd', 1.0),
new Edge<>('c', 'd', 3.0)
);
List<Path<Character>> paths = new DefaultKShortestPathFinder<Character>().findShortestPaths('a', 'b', graph, 2);
for(Path<Character> path:paths) {
System.out.println('h');
System.out.println(path.toString() + " cout: " + path.pathCost());
}
}
}
Everything works fine for a directed graph, but i want to modify it so it can calculate k-shortest paths for undirected graph anyone has an idea on how to achieve that, also i do know that for directed graph in adjacency matrix [a][b] = True but for [b][a] = false.对于有向图一切正常,但我想修改它,以便它可以计算无向图的 k 最短路径,任何人都知道如何实现这一点,我也知道邻接矩阵 [a][ b] = True 但对于 [b][a] = false。
An undirected graph is just a directed graph where for every edge a->b, there also exists the edge b->a. 无向图只是有向图,其中对于每个边a-> b,也存在边b-> a。 Just convert the undirected graph to a directed graph and use your existing algorithm.
只需将无向图转换为有向图并使用现有算法即可。
did you do ?你做了吗? ı need undirected graph code can u help me ?
我需要无向图代码你能帮我吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.