我正在使用圖表控件,其中包含一個包含指向其父母及其子女的鏈接的節點。我想扁平化樹,但要按順序。什麼是最快和最有效的方式來做到這一點;最好用C#。從樹(圖)中獲取有序列表的最有效方法是什麼?
這裏是一個樹的例子。我很難提出對訂單的很好的描述,所以我很抱歉。訂單應按照其創建順序列出所有節點。例如,在樹木擊打中,有效順序是(Root,A,B,C,G,D,H,E,F)。這個命令保證沒有節點被添加到它的父節點之前的列表中。
我正在使用圖表控件,其中包含一個包含指向其父母及其子女的鏈接的節點。我想扁平化樹,但要按順序。什麼是最快和最有效的方式來做到這一點;最好用C#。從樹(圖)中獲取有序列表的最有效方法是什麼?
這裏是一個樹的例子。我很難提出對訂單的很好的描述,所以我很抱歉。訂單應按照其創建順序列出所有節點。例如,在樹木擊打中,有效順序是(Root,A,B,C,G,D,H,E,F)。這個命令保證沒有節點被添加到它的父節點之前的列表中。
您的圖形沒有樹,因爲一個節點可以有多個父母。我假設你有一個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瞭解更多詳情。
謝謝你的算法。我的術語缺乏,所以我感謝您的幫助。你能詳細說明會導致堆棧溢出的原因嗎?循環引用會導致這種情況嗎? – Kingamoon
我假設你沒有循環引用。如果有圓圈,此代碼將失敗。維基百科就如何處理這種情況提出了建議。 – CodesInChaos
我在說一個圖,從最低的孩子到根的鏈很長(約10000個節點)。 – CodesInChaos
「按順序」是什麼意思?根節點是在中間還是在結果列表的開始處? – tjameson
基本上,一個節點不能被插入列表中,如果父節點沒有在那裏。根源將在一開始。 – Kingamoon
那麼順序會在葉節點左邊?還是有其他一些排序? – tjameson