简体   繁体   中英

C# populate a hierarchy tree from bottom to top

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.

The approach would be something like this:

  1. Create a node for each value
  2. Add each node as a child to its parent node
  3. Find all non root nodes, ie all nodes that are children to another node.
  4. Find all root nodes, ie the inverse of step 3.

Example with some assumptions:

  1. The table is given as a list of id and parent-id

  2. 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; }

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM