Java:如何表示图?

Java:如何表示图?,java,graph,Java,Graph,我正在实现一些算法来自学图形以及如何使用它们。在Java中,您推荐哪种方法是最好的?我是这样想的: public class Vertex { private ArrayList<Vertex> outnodes; //Adjacency list. if I wanted to support edge weight, this would be a hash map. //methods to manipulate outnodes } public cla

我正在实现一些算法来自学图形以及如何使用它们。在Java中,您推荐哪种方法是最好的?我是这样想的:

public class Vertex {

    private ArrayList<Vertex> outnodes; //Adjacency list. if I wanted to support edge weight, this would be a hash map.

    //methods to manipulate outnodes
}

public class Graph {
    private ArrayList<Vertex> nodes;
    //algorithms on graphs
}
但基本上是我编的。有更好的办法吗


另外,我希望它能够支持普通图的变体,如有向图、加权边、多重图等。

如果需要加权边和多重图,可能需要添加另一个类边

我还建议使用泛型来指定当前使用的顶点和边的子类。例如:

public class Graph<V extends Vertex> {
List<V> vertices;
...
}
当涉及到实现图形算法时,您还可以为图形类定义接口,算法可以在这些接口上运行,这样您就可以使用实际图形表示的不同实现。例如,连接良好的简单图可能更好地由实现,更稀疏的图可能由-这一切取决于


顺便说一句,高效地建造这样的结构可能是相当具有挑战性的,所以也许你可以给我们一些关于你想用它们做什么工作的更多细节?对于更复杂的任务,我建议您看看各种Java图形库,以获得一些灵感

看看图形库。您仍然可以练习实现自己的算法,可以从广度优先或深度优先搜索开始,但您不必担心创建图形结构。

很久以前,我也遇到过同样的问题,并且自己实现了。我建议您实现另一个类:Edge。然后,顶点将有一个边列表

public class Edge {
    private Node a, b;
    private directionEnum direction;     // AB, BA or both
    private int weight;
    ...
}
这对我有用。但也许这很简单。如果您仔细研究它的代码,这个库可能会对您有所帮助:

我强烈建议您在需要渲染图形时使用它


和它的同伴们:一起来看看。

即使在这个问题出现的时候,三年多以前,它还是完全自由存在的,并且在图论方面相当出色。但是,在2012年,它是最好的图论工具。因此,Sage已经内置了大量的图论材料,包括其他免费的开源材料。因此,简单地处理各种各样的事情来学习更多是很容易的,因为不需要编程

而且,如果您对编程部分也感兴趣,那么first Sage是开源的,因此您可以看到任何已经存在的代码。第二,如果你真的想练习,你可以重新编程任何你想要的函数,或者你可以第一个编程一些不存在的函数。在后一种情况下,您甚至可以提交该新功能,使Sage更好地为所有其他用户服务


此时,这个答案可能对OP没有多大用处,因为已经三年了,但希望它对将来看到这个问题的任何人都有用。

为什么不保持简单,使用或?

图的邻接列表实现适合解决大多数与图相关的问题


我的博客上也有同样的Java实现

每个节点的名称都是唯一的,并且知道它连接到谁。连接列表允许一个节点连接到任意数量的其他节点

class Graph<E> {
    private List<Vertex<E>> vertices;

    private static class Vertex<E> {
        E elem;
        List<Vertex<E>> neighbors;
    }
}
public class Node {
    public String name;
    public List<Edge> connections;
}
图形只是节点的集合。代替列表考虑按名称快速查找的映射。< /P>
public class Graph {
    List<Node> nodes;
}

由“罗伯特·塞奇威克”和“凯文·韦恩”撰写的简单陈述可在

从上页复制的解释

Graph类表示顶点的无向图 通过V-1命名为0

它支持以下两个主要操作:向图形添加边, 迭代与顶点相邻的所有顶点。它还提供 返回顶点数V和顶点数V的方法 允许平行边和自环。 按照惯例,自循环v-v出现在 v的邻接列表两次,并为度贡献两次 关于v

此实现使用邻接列表表示,它 是袋对象的顶点索引数组。 在最坏的情况下,所有操作都需要固定的时间,除了 在与给定顶点相邻的顶点上迭代,这需要 与这些顶点的数量成比例的时间

在学习算法时,在决定表示形式时不应考虑编程语言Java。每个问题都可以从一个独特的表示中受益,而且设计它可以增加一点学习。首先解决问题而不依赖于特定的语言,然后任何特定语言的表示将自然流动

当然,通用表示法和库在实际应用中很有用。但其中一些也可以从一些定制中受益。使用其他答案了解不同的技术可用,但考虑定制时

吃了。

我真的没有任何细节。。。我的自学目标是开放的。我只想建立一些图,找到一些最小生成树,对graphviz做一些输出,计算拓扑排序,等等。你能解释一下如何使用泛型吗?啊,谢谢你的解释。如果只是为了玩玩,我想邻接列表会很好地发挥作用。。。它似乎不是性能密集型的。希望我澄清了泛型部分。graphviz是合法的。您是否推荐一些方法来简化从Java数据结构到graphviz.dot文件的转换,并可能直接从Java生成图像?是的,请看一下Laszlo Szathmary的graphviz类:,以及Not丑恶的.xls:Laszlo的很好,但在运行演示时它会给我一个空指针异常。不太令人鼓舞。我有一个代码示例,运行良好。你做错了什么。谢谢你建议使用图形维兹:我只想说,项目的官方主页在这里:。图形中的bfs和dfs?你的边只知道顶点的名称。因此,您无法使用所显示的结构遍历图。使用从节点名称重新创建节点的附加逻辑,我们仍然可以进行遍历。我这样做是为了节省空间,这样我们就不必在Edge中再次保存完整的顶点。这就像只保存外部表中的主键。当一个对象作为类成员引用另一个对象时,它不会将完整对象保存在该表中。它只是指向另一个对象的指针。例如,如果两条边引用同一个顶点,则不会有数据重复。是的,谢谢,即使我只保存了名称,我如何检索完整的顶点,而不将它们保存在另一个映射名称到顶点的贴图中。作为辅助工具,您可能会有另一个用于按名称快速查找顶点的贴图,但在图形通常具有相互直接引用的顶点和边。这样,您就可以编写一种方法,只需访问顶点并沿着其边遍历图形。也许最好将连接命名为邻居。另外,如果我们不单独使用边,我们已经知道它的起点,因此可以在大多数用例中删除它以提高空间效率。可以想象一个不包含边的图。如果你没有;我的意思是我们应该把边作为一个列表,这对于大多数问题来说是一个很好的策略,但是我们可能不需要边对象中的Node start对象,因为当遍历图的节点时,我们知道遍历的节点就是开始。顺便说一句,连接可以改为边缘,我的建议是一个更糟糕的名字:你从什么开始?我正在为考试做准备,我还有一天的时间。我将不得不为少量节点编写一个程序。我也想到了和你一样的方法。似乎是Python。这个问题显然是关于Java的。
public class Edge {
    public Node start;
    public Node end;
    public double weight;
}
public class Graph {
    List<Node> nodes;
}