Java JGraphT-将BFS应用于加权图

Java JGraphT-将BFS应用于加权图,java,graph,breadth-first-search,jgrapht,Java,Graph,Breadth First Search,Jgrapht,我已经编写了为加权图寻找最佳路径的代码: SimpleDirectedWeightedGraph<String, DefaultWeightedEdge> graph = new SimpleDirectedWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class); graph.addVertex("1"); graph.addVertex("2"); gra

我已经编写了为加权图寻找最佳路径的代码:

SimpleDirectedWeightedGraph<String, DefaultWeightedEdge> graph =
                new SimpleDirectedWeightedGraph<String, DefaultWeightedEdge>(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("Shortest path from vertex 1 to vertex 3:");
List shortest_path = DijkstraShortestPath.findPathBetween(graph, "1", "3");
System.out.println(shortest_path);
SimpleDirectedWeightedGraph图=
新的SimpleDirectedWeightedGraph(DefaultWeightedEdge.class);
图。添加顶点(“1”);
图.添加顶点(“2”);
图。添加顶点(“3”);
图。添加顶点(“4”);
图。添加顶点(“5”);
DefaultWeightedEdge e1=图形添加(“1”、“2”);
图.设定的光线(e1,5);
DefaultWeightedEdge e2=图形添加(“2”、“3”);
图.设定的光线(e2,10);
DefaultWeightedEdge e3=图形添加(“2”、“4”);
图.设定的光线(e3,2);
DefaultWeightedEdge e4=图形添加(“4”、“5”);
图.设定的光线(e4,2);
DefaultWeightedEdge e5=图形添加(“5”、“3”);
图.设定的光线(e5,2);
System.out.println(“从顶点1到顶点3的最短路径:”;
列出最短路径=DijkstraShortestPath.findPathBetween(图“1”、“3”);
System.out.println(最短路径);

它返回正确的最短路径:
1->2->4->5->3
。我现在的问题是-对于同一个图,我希望获得包含顶点之间最少传输次数的路径(在本例中,它将是
1->2->3
)。对于这个用例,BFS将是完美的解决方案。有没有一种方法可以使用JGraphT API中的
breadthfirsterator
,或者我必须自己编写算法?

最简单的解决方案是忽略每个边权重,并根据Dijkstra算法计算最短路径

可以使用类从加权有向图创建未加权有向图。这只是覆盖每个边的
getedgewight
方法,并返回
1.0
,即默认权重

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

谢谢,这更接近我想要的,而且会给我想要的灵魂。但是我认为它可能比仅仅遍历图形慢得多,因为它需要额外的计算(这很重要,因为实际上我的图形非常庞大)。有没有一种方法可以通过广度优先搜索遍历图形?谢谢!我将检查这段代码是否有效,但它正是我想要的。编辑:快乐10k积分:)
public class Test {

    public static void main(String[] args) {
        SimpleDirectedWeightedGraph<String, DefaultWeightedEdge> graph =
                new SimpleDirectedWeightedGraph<String, DefaultWeightedEdge>(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 <V, E> List<E> findPathBetween(Graph<V, E> graph, V startVertex, V endVertex) {
        MyBreadthFirstIterator<V, E> iter = new MyBreadthFirstIterator<>(graph, startVertex);
        while (iter.hasNext()) {
            Object vertex = iter.next();
            if (vertex.equals(endVertex)) {
                return createPath(iter, endVertex);
            }
        }
        return null;
    }

    private static <V, E> List<E> createPath(MyBreadthFirstIterator<V, E> iter, V endVertex) {
        List<E> path = new ArrayList<E>();
        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<V, E> extends BreadthFirstIterator<V, E> {

        public MyBreadthFirstIterator(Graph<V, E> 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);
        }

    }
}