繁体   English   中英

如何在Java中构建加权有向无环图

[英]How to build in Java a Weighted Directed Acyclic Graph

我在类似的主题上进行了搜索,但是对于我的理解和理解水平来说,答案太模糊了,我认为它们对我的问题不够具体。

类似线程:
树(有向无环图)实现
表示DAG(有向无环图)

题:

我已经格式化了一个文本文件,其中包含以下格式的数据...
示例数据集:
GO:0000109#is_a:GO:0000110#is_a:GO:0000111#is_a:GO:0000112#is_a:GO:0000113#is_a:GO:0070312#is_a:GO:0070522#is_a:GO:0070912#is_a:GO: 0070913#is_a:GO:0071942#part_of:GO:0008622
GO:0000112#part_of:GO:0000442
GO:0000118#is_a:GO:0016581#is_a:GO:0034967#is_a:GO:0070210#is_a:GO:0070211#is_a:GO:0070822#is_a:GO:0070823#is_a:GO:0070824
GO:0000120#is_a:GO:0000500#is_a:GO:0005668#is_a:GO:0070860
GO:0000123#is_a:GO:0005671#is_a:GO:0043189#is_a:GO:0070461#is_a:GO:0070775#is_a:GO:0072487
GO:0000126#is_a:GO:0034732#is_a:GO:0034733
GO:0000127#part_of:GO:0034734#part_of:GO:0034735
GO:0000133#is_a:GO:0031560#is_a:GO:0031561#is_a:GO:0031562#is_a:GO:0031563#part_of:GO:0031500
GO:0000137#part_of:GO:0000136

我正在根据此数据构建加权定向DAG(以上只是代码段)。 整个106kb的数据集在这里: 来源

--------------------------------------------------

考虑到逐行,每行的数据解释如下...
第一行为例:
GO:0000109#is_a:GO:0000110#is_a:GO:0000111#is_a:GO:0000112#is_a:GO:0000113#is_a:GO:0070312#is_a:GO:0070522#is_a:GO:0070912#is_a:GO: 0070913#is_a:GO:0071942#part_of:GO:0008622

“#”是行数据的分隔符/标记。
第一项,GO:0000109是节点名称。
is_a:GO:xxxxxxx或part_of:GO:xxxxxxx的后续术语是连接到GO:0000109的节点。
如数据集中所示,某些后续术语也具有连接。
当is_a时,边缘的权重为0.8。
当为part_of时,边缘的权重为0.6。

--------------------------------------------------

我对DAG的使用方式有Google-d的知识,并且我了解这个概念。 但是,我仍然不知道如何将其放入代码中。 我正在使用Java。
据我了解,图通常由节点和弧组成。 该图是否需要邻接表来确定连接方向? 如果是这样,我不确定如何将图形和邻接表结合在一起进行通信。 构建完图之后,我的第二个目标是从根节点中找出每个节点的度数。 数据集中有一个根节点。

为了说明,我绘制了下面第一行数据的连接示例:
图片链接

我希望你们能理解我在这里想要实现的目标。 感谢您浏览我的问题。 :)

因为考虑起来比较容易,所以我宁愿将它表示为一棵树。 (这也使遍历地图和保持中间度更加容易。)

您可能有一个Node类,该类将具有子Node对象的集合。 如果需要,还可以将子关系表示为一个Relationship对象,该对象既具有权重又具有Node指针,并且可以存储“ Relationship对象的集合。

然后,您可以从根开始在树上散步,并用度数标记每个访问的节点。

class Node{
    String name;
    List<Relationship> children;
}

class Relationship{
    Node child;
    double weight;
}

class Tree{
    Node root;
}

在这里, Tree可能应该具有这样的方法:

public Node findNodeByName(String name);

Node可能应该具有这样的方法:

public void addChild(Node n, double weight);

然后,在解析每一行时,您调用Tree.findNodeByName()来找到匹配的节点(如果不存在,则创建一个节点...但是如果您的数据很好,那不应该发生),然后在到该节点的线。

正如您所指出的,DAG不能真正转换为树,尤其是因为某些节点具有多个父节点。 可以做的是插入与多个父级的子级相同的节点,也许使用哈希表来确定是否遍历了特定节点。

阅读评论后,您似乎对节点如何包含关系(每个关系又包含一个节点)感到困惑。 这是相当普遍的策略,通常称为“复合模式”。

就树而言,其想法是可以将树视为由多个子树组成-如果您要从树上断开节点及其所有祖先的连接,则断开连接的节点仍会构成一棵树,尽管它是较小的树。 因此,代表一棵树的自然方法是让每个节点包含其他节点作为子节点。 这种方法使您可以递归地执行许多操作,对于树木来说,这通常又是自然的。

让节点跟踪其子节点,树的其他部分也不会模仿数学有向图-每个顶点仅“知道”其边缘,而没有其他任何东西。

递归树实现示例

例如,要在二元搜索树中搜索元素,可以调用根的搜索方法。 然后,根检查所寻找的元素是否等于,小于或大于其自身。 如果相等,则搜索以适当的返回值退出。 如果小于或大于,则根将分别调用左侧或右侧子级的搜索,它们将做完全相同的事情。

类似地,要将新节点添加到树中,您将以新节点为参数调用根的add方法。 根决定是采用新节点还是将其传递给其子节点之一。 在后一种情况下,它将选择一个子节点,并使用新Node作为参数调用其add方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM