JGraphT - apply BFS to WeightedGraph

前端 未结 1 915
孤独总比滥情好
孤独总比滥情好 2021-01-21 20:20

I have written the code finding the optimal path for a Weighted Graph:

SimpleDirectedWeightedGraph graph =
                new         


        
1条回答
  •  后悔当初
    2021-01-21 21:11

    The simplest solution would be to ignore each of the edge weights and calculate the shortest path as per Dijkstra's algorithm.

    It is possible to create an unweighted directed graph from a weighted directed graph with the AsUnweightedDirectedGraph class. This simply overrides the getEdgeWeight method for each edge and returns 1.0, i.e. the default weight.

    Graph unweightedGraph = new AsUnweightedDirectedGraph<>(graph);
    List path = DijkstraShortestPath.findPathBetween(unweightedGraph, "1", "3");
    System.out.println(path); // prints [(1 : 2), (2 : 3)]
    

    This might not provide the best performance. To improve it, you can build your own BreadthFirstIterator to just iterate through the graph. This code is based on this class, but updated to match the more recent versions of JGraphT. It provides a BFSShortestPath class that finds the shortest path between two vertices with a BFS, whatever the weight on each edge.

    public class Test {
    
        public static void main(String[] args) {
            SimpleDirectedWeightedGraph graph =
                    new SimpleDirectedWeightedGraph(DefaultWeightedEdge.class);
            graph.addVertex("1");
            graph.addVertex("2");
            graph.addVertex("3");
            graph.addVertex("4");
            graph.addVertex("5");
    
            DefaultWeightedEdge e1 = graph.addEdge("1", "2");
            graph.setEdgeWeight(e1, 5);
            DefaultWeightedEdge e2 = graph.addEdge("2", "3");
            graph.setEdgeWeight(e2, 10);
            DefaultWeightedEdge e3 = graph.addEdge("2", "4");
            graph.setEdgeWeight(e3, 2);
            DefaultWeightedEdge e4 = graph.addEdge("4", "5");
            graph.setEdgeWeight(e4, 2);
            DefaultWeightedEdge e5 = graph.addEdge("5", "3");
            graph.setEdgeWeight(e5, 2);
    
            System.out.println(BFSShortestPath.findPathBetween(graph, "1", "3"));
        }
    
    }
    
    final class BFSShortestPath {
    
        private BFSShortestPath() {} // ensure non-instantiability.
    
        public static  List findPathBetween(Graph graph, V startVertex, V endVertex) {
            MyBreadthFirstIterator iter = new MyBreadthFirstIterator<>(graph, startVertex);
            while (iter.hasNext()) {
                Object vertex = iter.next();
                if (vertex.equals(endVertex)) {
                    return createPath(iter, endVertex);
                }
            }
            return null;
        }
    
        private static  List createPath(MyBreadthFirstIterator iter, V endVertex) {
            List path = new ArrayList();
            while (true) {
                E edge = iter.getSpanningTreeEdge(endVertex);
                if (edge == null) {
                    break;
                }
                path.add(edge);
                endVertex = Graphs.getOppositeVertex(iter.getGraph(), edge, endVertex);
            }
            Collections.reverse(path);
            return path;
        }
    
        private static class MyBreadthFirstIterator extends BreadthFirstIterator {
    
            public MyBreadthFirstIterator(Graph g, V startVertex) {
                super(g, startVertex);
            }
    
            @Override
            protected void encounterVertex(V vertex, E edge) {
                super.encounterVertex(vertex, edge);
                putSeenData(vertex, edge);
            }
    
            @SuppressWarnings("unchecked")
            public E getSpanningTreeEdge(V vertex) {
                return (E) getSeenData(vertex);
            }
    
        }
    }
    

    0 讨论(0)
提交回复
热议问题