java - 使用 JGraphT 库的 EdgeProvider 类

标签 java generics graph graphviz jgrapht

我已经四处寻找解决方案,但由于我对 Java 的通用编程风格没有太多经验,我对使用什么词来搜索这个问题有点困惑。我正在尝试使用 JGraphT 库中的 DOTImporter ( http://jgrapht.org/javadoc/org/jgrapht/ext/DOTImporter.html ),这又要求我使用 EdgeProvider 接口(interface) ( http://jgrapht.org/javadoc/org/jgrapht/ext/EdgeProvider.html )。我尝试了多种方法来实现这一点,但 buildEdge 使用通用返回类型这一事实让我感到非常困惑。我也尝试使用他们的 DefaultEdge ( http://jgrapht.org/javadoc/org/jgrapht/graph/DefaultEdge.html ),这并没有好多少,因为他们的 API 指定了两种获取几个字段(源和目标)的方法,但没有办法设置这些字段,由于它们不是公开的,并且构造函数没有参数,所以我不太确定应该如何设置它们。

为了说明这一点,我正在尝试加载一个 .dot 文件,我真正关心的是标签,所以我的图实际上将由字符串顶点组成,因此边将是 (String, String)结构也是如此。它确实非常简单,因此我不会介意实现我自己的图形结构来使用它,但我确实想利用 DOTImporter。

如果有人可以为我提供一些关于如何正确实现 EdgeProvider 的具体类以及如何使用 DefaultEdge 类的帮助,我将非常感激。

最佳答案

简短回答:这是 DOTImporter 的完整示例(非常简单......):

1.4.x 之前的 JGraphT 版本的示例代码:

public class DOTTest {

    public static void main(String[] args) throws ImportException {
        //Example graph
        String input =
                "digraph graphname {\r\n" + "     a -> b -> c;\r\n" + "     b -> d;\r\n" + " }";

        GraphImporter<String, DefaultEdge> importer = new DOTImporter<>(
                (label, attributes) -> label, 
                (from, to, label, attributes) -> new DefaultEdge()
        );

        Graph<String, DefaultEdge> result = new SimpleDirectedGraph<>(DefaultEdge.class);
        importer.importGraph(result, new StringReader(input));

        System.out.println(result);
    }
}

JGraphT 1.5.0 及更高版本的新示例代码:

public class DOTTest {

    public static void main(String[] args) throws ImportException {
        //Example graph
        String input =
                "digraph graphname {\r\n" + "     a -> b -> c;\r\n" + "     b -> d;\r\n" + " }";

    Graph<String, DefaultEdge> result = new SimpleDirectedGraph<>(DefaultEdge.class);

    DOTImporter<String, DefaultEdge> dotImporter = new DOTImporter<>();
    dotImporter.setVertexFactory(label -> label);
    dotImporter.importGraph(result, new StringReader(input);

    System.out.println(result);
}

}

请注意,在 JGraphT 中,每个类都带有一个相应的测试类,其中包含许多示例。

更长的答案: 在 JGraphT 中,每个顶点和每条边都是一个对象。这允许非常灵活的图表。缺点是需要提供工厂方法。例如,如果您调用 graph.addEdge(u,v),则必须创建一个新对象来表示 u 和 v 之间的边。为此,需要一个边工厂。在许多实际情况下,用户不需要自定义边缘对象。对于这些情况,JGraphT 提供了 DefaultEdge 类。您希望拥有自定义边的一个实际示例是,例如,当您构建表示道路网络的图形时。顶点可以是交叉路口,边可以是街道。例如,街道对象将存储车道数量、行驶速度、行驶方向等。

那么 IntrusiveEdge 的用途是什么?除非您打算向 JGraphT 贡献代码,否则这并不重要。您绝对不应该直接使用 IntrusiveEdge。 IntrusiveEdge 是大多数边缘的基本类型。在底层,它存储边的源、目标和权重。然而,这些字段是隐藏的,即它们不能直接访问!相反,图类提供了访问这些字段的方法,例如graph.getEdgeSource(myEdge)。

关于java - 使用 JGraphT 库的 EdgeProvider 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44641596/

相关文章:

c++ - 如果边未按权重排序顺序插入双端队列中,0-1 BFS 是否会产生正确的答案?

JavaFX:如何创建带有通知徽章的应用程序图标?

java - 如何根据 map 结果过滤流

java - 尝试对两个不同长度的数组求和时出错

java - 如何使用 JAXB (xjc) 为全局元素生成 POJO?

generics - 具有 ifort 编译器的通用内部过程

generics - 为什么不能在Rc <dyn Fn()>内使用此闭包?

java - Spring CrudRepository : why to invent a new generic type S

c++ - 迭代 DFS 与递归 DFS 和不同的元素顺序

algorithm - 图与 BFS 和 DFS 树的等价性