2013-07-01 56 views
0

我有一堆數據將被表示爲一棵樹。我正在使用的控件需要正確排序數據。c#對鄰接樹中的數據進行排序

這是每個節點的結構:我需要的方式對數據進行排序

public class TreeNode 
{ 
    public Guid id { get; set; } 
    public string name { get; set; } 
    public int level { get; set; } 
    public Guid? parent { get; set; } 
    public bool isLeaf { get; set; }  
} 

讓我有樹節點的列表與根第一,其次是它的孩子等等。換句話說,所有直接的孩子都需要關注列表中的父母。

我還希望子節點和葉節點按名稱排序。 (> =擴張,o =葉)

root > 
    level1a >   
    level1b > 
    level2d > 
    level2a o 
    level1a o 
    level1b o 

是否有一個簡單的方法來做到這一點?

我假設我需要一些遞歸函數,而不是將無法使用的順序組合的語句排序它(像list.OrderBy(x => x.parent).ThenBy(x => x.level).ThenBy(x => x.isLeaf);

回答

1

你是正確的,用一個單一的LINQ這樣做表達不直截了當。這種遞歸的方法應該做的伎倆:

IEnumerable<TreeNode> TreeOrder(
    IEnumerable<TreeNode> nodes) 
{ 
    //Find the root node 
    var root = nodes.Single(node => node.parent == null); 

    //Build an inverse lookup from parent id to children ids 
    var childrenLookup = nodes 
     .Where(node => node.parent != null) 
     .ToLookup(node => node.parent.Value); 

    return TreeOrder(root, childrenLookup); 
} 

IEnumerable<TreeNode> TreeOrder(
    TreeNode root, 
    ILookup<Guid, TreeNode> childrenLookup) 
{ 
    yield return root; 

    if (!childrenLookup.Contains(root.id)) 
     yield break; 

    foreach (var child in childrenLookup[root.id]) 
     foreach (var node in TreeOrder(child, childrenLookup)) 
      yield return node; 
} 
+0

您可以比較輸入數據與目錄和文件。 'isLeaf'屬性表示:「是文件?」。順序應該對應**按名稱排序的董事樹的擴展順序**。列表中的拳頭應該是「A」。列表中的最後一個應該是「文件」(具有'isLeaf === true'的項目)的「A」。如果所有項目都是「目錄」,那麼正確的順序應該是「ABDECFG」。如果一個目錄同時包含子目錄*和*文件,那麼應該列出第一個子目錄,然後列出這些文件。 – Oleg

+0

@Timothy:奧列格說了什麼:) ABDECFG – woggles

+0

@Timothy,不會編譯:'foreach(TreeOrder中的var節點(childrenLookup [root.id])'TreeOrder沒有重載需要1個參數,我也改變了'.Where node.parent.HasValue)'到'.Where(node => node.parent.HasValue)' – woggles