通用树结构 - 如何填充组织结构图

时间:2016-03-22 07:21:46

标签: c# linq generics tree

我有一个应该是一个相当微不足道的问题,但我想确保我能做到最好"优雅"可能在.Net 4.5中,我喜欢比我聪明的人的一些意见。

我有一个代表通用树结构的类:

   public class TreeNode<T>
    {
        List<TreeNode<T>> Children;

        T Item {get;set;}

        public TreeNode (T item)
        {
            Item = item;
        }

        public TreeNode<T> AddChild(T item)
        {
            TreeNode<T> nodeItem = new TreeNode<T>(item);
            Children.Add(nodeItem);
            return nodeItem;
        }
    }

现在,我有一个代表该组织员工的Person类。每个Person对象都有IDBossID指向其上级。

多名员工可以拥有相同的老板,因此我尝试使用此树结构创建组织结构图。

顶级节点将成为Person对象,其中BossID为空(它是int?)。我可以快速使用LINQ。

这是令我困惑的下一步。有多种方法,但它们对我来说似乎有点草率,我知道必须有一种更容易/更优雅的方式来填写组织结构图的其余部分。

所以现在我有一个List<Person>的通用对象,包含所有员工,以及他们可以添加子节点的各种BossID和这种通用树结构。

这一切都非常基础,但填充树的正确顺序是什么?我递归地应该迭代这条线吗?我知道这里有回溯,这是我被难倒的地方。

我道歉,我的背景不是计算机科学,如果是我意识到树结构,链表和其他一切都是微不足道的东西。但这是我的第一次尝试,我想看看它是如何正确完成的。

我感谢任何指导。

1 个答案:

答案 0 :(得分:2)

所以,假设您有一个Person类定义为:

public class Person
{
    public int ID;
    public int? BossID;
}

...并且您将List<Person>定义为people,然后就可以了:

var lookup = people.ToLookup(p => p.BossID);

Action<TreeNode<Person>> addChildren = null;
addChildren = p =>
{
    foreach (var child in lookup[p.Item.ID])
    {
        var childNode = p.AddChild(child);
        addChildren(childNode);
    }
};

var trees =
    from boss in lookup[null]
    select new TreeNode<Person>(boss);

foreach (var tree in trees)
{
    addChildren(tree);
}

这假设您可能有一个以上null老板的人。如果你没有那么好,只需运行此代码并执行trees.First()

我使用的TreeNode<T>的定义是:

public class TreeNode<T>
{
    private List<TreeNode<T>> Children;

    public T Item { get; set; }

    public TreeNode(T item)
    {
        this.Item = item;
        this.Children = new List<TreeNode<T>>();
    }

    public TreeNode<T> AddChild(T item)
    {
        var nodeItem = new TreeNode<T>(item);
        this.Children.Add(nodeItem);
        return nodeItem;
    }
}

你可以将TreeNode<T>简化为:

public class TreeNode<T> : List<TreeNode<T>>
{
    public T Item { get; set; }

    public TreeNode(T item)
    {
        this.Item = item;
    }
}

...然后您需要将addChildren修改为:

Action<TreeNode<Person>> addChildren = null;
addChildren = p =>
{
    foreach (var child in lookup[p.Item.ID])
    {
        var childNode = new TreeNode<Person>(child);
        p.Add(childNode);
        addChildren(childNode);
    }
};

...但是您可以使用List<>的所有标准TreeNode<T>运算符。