我有一个应该是一个相当微不足道的问题,但我想确保我能做到最好"优雅"可能在.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
对象都有ID
和BossID
指向其上级。
多名员工可以拥有相同的老板,因此我尝试使用此树结构创建组织结构图。
顶级节点将成为Person
对象,其中BossID
为空(它是int?
)。我可以快速使用LINQ。
这是令我困惑的下一步。有多种方法,但它们对我来说似乎有点草率,我知道必须有一种更容易/更优雅的方式来填写组织结构图的其余部分。
所以现在我有一个List<Person>
的通用对象,包含所有员工,以及他们可以添加子节点的各种BossID
和这种通用树结构。
这一切都非常基础,但填充树的正确顺序是什么?我递归地应该迭代这条线吗?我知道这里有回溯,这是我被难倒的地方。
我道歉,我的背景不是计算机科学,如果是我意识到树结构,链表和其他一切都是微不足道的东西。但这是我的第一次尝试,我想看看它是如何正确完成的。
我感谢任何指导。
答案 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>
运算符。