Reputation: 57
I have to fill an hierarchy tree starting from bottom to top, starting from a node till its root node: I have a table with a many to one relation inside, which contains the id of a subordinate and the id of its superior.
PK | SUBORDINATE_ID | SUPERIOR_ID
1 | 50 | 22
2 | 51 | 22
3 | 52 | 22
4 | 22 | 10
5 | 10 | 1
6 | 60 | 2
7 | 70 | 3
8 | 80 | 4
How can I efficently traverse the table and fill a structure to fit my needs? Which structure should I use considering that there could be more then one root nodes?
For example 4 Co-founders would be my 4 root nodes but they can be more then 4 in the future
A structure that could fit my needs would be a list of class like this
public class HierarchyMember
{
public int Id { get; set; }
public List<HierarchyMember> Children { get; set; }
}
But it's not practical in the usage with LINQ and also it's hard to fill from bottom to top.
Upvotes: 1
Views: 1553
Reputation: 36639
The approach would be something like this:
Example with some assumptions:
The table is given as a list of id and parent-id
Roots are marked by having the same id and parent id, replace with whatever is appropriate in your case.
public class HierarchyMember
{
public int Id { get; }
public List<HierarchyMember> Children { get; } = new List<HierarchyMember>();
public HierarchyMember(int id) => Id = id;
}
public static IEnumerable<HierarchyMember> BuildTree(List<(int Id, int ParentId)> hierarchy)
{
var dictionary = hierarchy.ToDictionary(p => p.Id, p => new HierarchyMember(p.Id));
foreach (var (id, parentId) in hierarchy)
{
if (id != parentId)
{
dictionary[parentId].Children.Add(dictionary[id]);
}
}
var nonRoots = dictionary.Values.SelectMany(p => p.Children).ToHashSet();
var roots = dictionary.Values.Where(p => !nonRoots.Contains(p)).ToList();
return roots;
}
Upvotes: 3