2012-11-21 65 views
-1

我正在使用圖表控件,其中包含一個包含指向其父母及其子女的鏈接的節點。我想扁平化樹,但要按順序。什麼是最快和最有效的方式來做到這一點;最好用C#。從樹(圖)中獲取有序列表的最有效方法是什麼?

這裏是一個樹的例子。我很難提出對訂單的很好的描述,所以我很抱歉。訂單應按照其創建順序列出所有節點。例如,在樹木擊打中,有效順序是(Root,A,B,C,G,D,H,E,F)。這個命令保證沒有節點被添加到它的父節點之前的列表中。

Simple Diagram to demo my question

+2

「按順序」是什麼意思?根節點是在中間還是在結果列表的開始處? – tjameson

+0

基本上,一個節點不能被插入列表中,如果父節點沒有在那裏。根源將在一開始。 – Kingamoon

+0

那麼順序會在葉節點左邊?還是有其他一些排序? – tjameson

回答

1

您的圖形沒有樹,因爲一個節點可以有多個父母。我假設你有一個directed acyclic graph (DAG)。您的有序列表稱爲該有向圖的toplogical ordering,當且僅當該圖是非循環圖時才存在。幸運的是,這樣的排序可以用線性運行時間產生。

您可以用深度優先搜索從根(S)開始這樣做:

public static IEnumerable<Node> GetTopologicalGraphOrdering(IEnumerable<Node> roots) 
{ 
    var list=new List<Node>(); 
    var visited=new HashSet<Node>(); 

    Action<Node> visit = null; 
    visit = (n)=> 
    { 
     if(visited.Add(n) 
     { 
      foreach(Node child in n.Children) 
      { 
       visit(child); 
      } 
      list.Add(n) 
     } 
    } 

    foreach(Node n in roots) 
    { 
     visit(n); 
    } 

    return list.Reverse(); 
} 

(未經測試的記事本代碼)

注意這個天真的實施將導致深堆棧溢出圖表。切換到顯式堆棧或替代算法,如果這成爲一個問題。

閱讀維基百科文章Topological sorting瞭解更多詳情。

+0

謝謝你的算法。我的術語缺乏,所以我感謝您的幫助。你能詳細說明會導致堆棧溢出的原因嗎?循環引用會導致這種情況嗎? – Kingamoon

+0

我假設你沒有循環引用。如果有圓圈,此代碼將失敗。維基百科就如何處理這種情況提出了建議。 – CodesInChaos

+0

我在說一個圖,從最低的孩子到根的鏈很長(約10000個節點)。 – CodesInChaos

相關問題