簡體   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