答案 0 :(得分:7)
将图形存储在数据库中非常简单:您有一个节点表和一个边表,它充当节点表和它自身之间的多对多关系表。像这样:
create table node (
id integer primary key
);
create table edge (
start_id integer references node,
end_id integer references node,
primary key (start_id, end_id)
);
然而,关于以这种方式存储图形存在一些棘手的问题。
首先,此方案中的边缘是自然导向的 - 开始和结束是不同的。如果你的边是无向的,那么你要么在编写查询时要小心,要么在表中为每个边存储两个条目,一个在任一方向(然后小心写查询!)。如果您存储单个边缘,我建议对存储的表单进行规范化 - 可能始终将具有最低ID的节点视为开始(并向表中添加检查约束以强制执行此操作)。你可以有一个真正无序的表示,没有边缘引用节点,而是在它们之间有一个连接表,但这对我来说似乎不是一个好主意。
其次,上面的模式无法表示多图。你可以很容易地扩展它来做到这一点;如果给定节点对之间的边缘是不可区分的,最简单的方法是向每个边缘行添加一个计数,说明所引用节点之间有多少条边。如果它们是可区分的,那么您将需要在节点表中添加一些内容以允许它们被区分 - 自动生成的边缘ID可能是最简单的事情。
但是,即使整理了存储,您也会遇到使用图表的问题。如果你想对内存中的对象进行所有处理,而数据库纯粹用于存储,那么没问题。但是如果你想对数据库中的图形进行查询,那么你将不得不弄清楚如何在SQL中执行它们,它没有对图形的任何内置支持,并且其基本操作不容易适应使用图表。它可以完成,特别是如果你有一个带有递归SQL支持的数据库(PostgreSQL,Firebird,一些专有数据库),但它需要一些思考。如果您想这样做,我的建议是发布有关特定查询的更多问题。
答案 1 :(得分:2)
这是一种可接受的方法。您需要考虑如何操纵该信息。您很可能需要一种与数据库分开的语言来执行此类数据所暗示的与图形相关的计算。 Skiena's Algorithm Design Manual有广泛的剖面图数据结构及其操作。
不考虑您可能执行的查询类型,请从两个表vertices
和edges
开始。顶点很简单,标识符和名称。鉴于多图,边缘很复杂。边缘应该由两个顶点(即外键)和一些附加信息的组合唯一地标识。附加信息取决于您正在解决的问题。例如,如果航班信息,出发和到达时间以及航空公司。此外,您需要确定边缘是否是定向的(即单向),并且如果该信息也是如此。
根据计算结果,您最终可能会遇到使用某种人工智能/机器学习算法更好地解决的问题。例如,最佳航班。书Programming Collective Intelligence为此目的提供了一些有用的算法。但是保存数据的地方并没有改变算法本身。
答案 2 :(得分:1)
嗯,信息必须存储在某处,关系数据库不是一个坏主意。
它只是一个多对多关系,一个节点列表表和一个边/连接列表表。
答案 3 :(得分:0)
考虑Facebook如何在他们的数据库中实现社交图。他们可能有一张供人们使用的桌子和另一张友谊桌子。友谊表至少有两列,每列都是人员表的外键。
由于友谊是对称的(在Facebook上),他们可能会确保第一个外键的ID始终小于第二个外键的ID。 Twitter有一个针对其社交网络的有向图,所以它不会使用这样的规范表示。