You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何基于JGraphT框架对有向图进行正向与反向遍历?

嘿,我来帮你搞定JGraphT 1.1.0里有向图的正向和反向遍历问题!你已经搭好了基础的有向图结构,先帮你补全一下代码里没写完的那条边,接下来咱们一步步实现两种遍历,甚至可以让它们同时跑起来~

首先补全你的图创建代码:

final Graph<String, DefaultEdge> directedGraph = new DefaultDirectedGraph<>(DefaultEdge.class);
directedGraph.addVertex("v1");
directedGraph.addVertex("v2");
directedGraph.addVertex("v3");
directedGraph.addVertex("v4");
directedGraph.addEdge("v1", "v4");
directedGraph.addEdge("v4", "v2");
directedGraph.addEdge("v2", "v3"); // 补全这条未完成的边

一、正向遍历(常规路径遍历)

JGraphT自带了现成的迭代器,直接用就能实现BFS(广度优先)或DFS(深度优先)遍历,完全不用自己造轮子:

正向BFS遍历示例

System.out.println("正向BFS遍历结果:");
BreadthFirstIterator<String, DefaultEdge> bfsIterator = new BreadthFirstIterator<>(directedGraph);
while (bfsIterator.hasNext()) {
    String vertex = bfsIterator.next();
    System.out.print(vertex + " ");
    // 如果需要同时输出边信息,可以遍历当前顶点的出边
    for (DefaultEdge edge : directedGraph.outgoingEdgesOf(vertex)) {
        System.out.print("(" + directedGraph.getEdgeSource(edge) + "->" + directedGraph.getEdgeTarget(edge) + ") ");
    }
}

正向DFS遍历示例

System.out.println("\n正向DFS遍历结果:");
DepthFirstIterator<String, DefaultEdge> dfsIterator = new DepthFirstIterator<>(directedGraph);
while (dfsIterator.hasNext()) {
    String vertex = dfsIterator.next();
    System.out.print(vertex + " ");
}

二、反向遍历(沿入边方向遍历)

要实现反向遍历,JGraphT提供了一个非常方便的ReverseGraph类——它会创建原有有向图的反向视图(不会复制数据,只是反转所有边的方向),这样你就能用和正向遍历完全一样的方式来遍历这个反向图,等价于沿原图形的入边方向遍历。

基于ReverseGraph的反向遍历示例

// 创建反向图视图(原图形修改会同步到这里,无需额外维护)
Graph<String, DefaultEdge> reversedGraph = new ReverseGraph<>(directedGraph);

// 反向BFS遍历(对应原图形的反向路径)
System.out.println("\n反向BFS遍历结果:");
BreadthFirstIterator<String, DefaultEdge> reversedBfsIterator = new BreadthFirstIterator<>(reversedGraph);
while (reversedBfsIterator.hasNext()) {
    String vertex = reversedBfsIterator.next();
    System.out.print(vertex + " ");
    // 这里的"出边"就是原图形的入边
    for (DefaultEdge edge : reversedGraph.outgoingEdgesOf(vertex)) {
        System.out.print("(" + reversedGraph.getEdgeSource(edge) + "->" + reversedGraph.getEdgeTarget(edge) + ") ");
    }
}

如果你不想创建反向图,也可以直接遍历每个顶点的入边来手动实现反向遍历:

// 手动遍历原图形的入边
System.out.println("\n手动反向遍历(遍历入边):");
for (String vertex : directedGraph.vertexSet()) {
    System.out.print("顶点" + vertex + "的入边:");
    for (DefaultEdge edge : directedGraph.incomingEdgesOf(vertex)) {
        System.out.print("(" + directedGraph.getEdgeSource(edge) + "->" + directedGraph.getEdgeTarget(edge) + ") ");
    }
    System.out.println();
}

三、同时进行正向与反向遍历

如果要让两种遍历同时执行,用Java多线程就能轻松实现,比如创建两个独立的线程分别处理正向和反向遍历:

// 正向遍历线程
Thread forwardThread = new Thread(() -> {
    System.out.println("[正向线程] 开始遍历:");
    BreadthFirstIterator<String, DefaultEdge> iterator = new BreadthFirstIterator<>(directedGraph);
    while (iterator.hasNext()) {
        System.out.print("[正向线程] " + iterator.next() + " ");
    }
    System.out.println("\n[正向线程] 遍历结束");
});

// 反向遍历线程
Thread reverseThread = new Thread(() -> {
    System.out.println("[反向线程] 开始遍历:");
    Graph<String, DefaultEdge> reversedGraph = new ReverseGraph<>(directedGraph);
    BreadthFirstIterator<String, DefaultEdge> iterator = new BreadthFirstIterator<>(reversedGraph);
    while (iterator.hasNext()) {
        System.out.print("[反向线程] " + iterator.next() + " ");
    }
    System.out.println("\n[反向线程] 遍历结束");
});

// 启动两个线程
forwardThread.start();
reverseThread.start();

// 可选:等待两个线程都执行完毕
try {
    forwardThread.join();
    reverseThread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

内容的提问来源于stack exchange,提问作者Hector

火山引擎 最新活动