I have what should be a fairly trivial problem but I want to make sure I'm doing this in the most "elegant" way possible in .Net 4.5 and I'd like some opinions from people smarter than me.
I have a class that represents a generic tree structure as such:
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;
}
}
Now, I have a Person class that represents an employee of the organization. Each Person
object has an ID
and a BossID
that points to their superior.
Multiple employees can have the same boss, hence why I am trying to create an organization chart with this tree structure.
The top node is going to be the Person
object where BossID
is null (it's an int?
). That I can quickly get with LINQ.
It's the next step that is puzzling me a bit. There are multiple approaches but they seem somewhat sloppy to me and I know there must be a much easier/elegant way to fill in the rest of the org chart.
So right now I have a generic object of List<Person>
holding all the employees, with their various BossID
s and this generic tree structure that I can add child nodes to.
It's all very basic, but what is the proper sequence to fill the tree? Am I recursively supposed to iterate down the line? I know there is backtracking involved here, which is where I'm getting stumped.
I apologize, my background is not in Computer Science, and if it was I realize that tree structures, linked lists, and everything else is trivial stuff. But this is my first attempt and I want to see how it's done properly.
I appreciate any guidance.
So, given you have a Person
class defined as this:
public class Person
{
public int ID;
public int? BossID;
}
...and you have a List<Person>
defined as people
then this works:
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);
}
This assumes that you may have more than one person with a null
boss. If you don't that's fine, just run this code and do trees.First()
.
The definition of TreeNode<T>
I used was this:
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;
}
}
You could shorten TreeNode<T>
to this though:
public class TreeNode<T> : List<TreeNode<T>>
{
public T Item { get; set; }
public TreeNode(T item)
{
this.Item = item;
}
}
...then your need to modify addChildren
to this:
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);
}
};
...but then you'd have all of the standard List<>
operators available for TreeNode<T>
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.