Constructing Tree Structures via Recursion in C#
Processing hierarchical datasets frequently necessitates transforming a flat collection into a nested tree format. In C#, recursion provides an efficient mechanism to traverse parent-child relationships defined by identifiers. The following implementation demonstrates how to retrieve complete sub-structures starting from a specific root ID.
Data Model Definition
First, define an entity class to represent individual nodes within the hierarchy. Each instance holds its unique identifier, a reference to its parent, and a collection for descendants.
public class CategoryNode
{
public int NodeId { get; set; }
public string DisplayName { get; set; }
public int ParentIdentifier { get; set; }
public List<CategoryNode> SubCategories { get; set; }
}
Hierarchy Construction Logic
The core logic involves filtering the dataset for direct children matching the target parent ID, then invoking the same method for each child to populate their respective branches. Using LINQ makes the filtering concise.
public class HierarchyService
{
public List<CategoryNode> ExpandTree(int rootId, List<CategoryNode> flatData)
{
// Filter immediate children for the given parent ID
var directMatches = flatData
.Where(n => n.ParentIdentifier == rootId)
.ToList();
if (!directMatches.Any())
{
return null;
}
// Map results recursively
return directMatches.Select(item => new CategoryNode
{
NodeId = item.NodeId,
DisplayName = item.DisplayName,
ParentIdentifier = item.ParentIdentifier,
// Recursively resolve the nested level
SubCategories = ExpandTree(item.NodeId, flatData)
}).ToList();
}
}
Example Dataset and Execution
To validate the approach, we initialize a mock dataset representing organizational departments. Note that multiple roots may exist if the Parent Identfiier is zero.
public void RunDemo()
{
var dataSet = new List<CategoryNode>
{
new CategoryNode { NodeId = 101, ParentIdentifier = 0, DisplayName = "Engineering" },
new CategoryNode { NodeId = 102, ParentIdentifier = 0, DisplayName = "Marketing" },
new CategoryNode { NodeId = 110, ParentIdentifier = 101, DisplayName = "Backend Team" },
new CategoryNode { NodeId = 111, ParentIdentifier = 101, DisplayName = "Frontend Team" },
new CategoryNode { NodeId = 115, ParentIdentifier = 110, DisplayName = "Database Unit" }
};
var service = new HierarchyService();
// Retrieve top-level nodes and their complete depth
var structuredResult = service.ExpandTree(0, dataSet);
Console.WriteLine(JsonConvert.SerializeObject(structuredResult, Formatting.Indented));
}
When executed, the resulting JSON structure reflects the nested relationships:
[
{
"NodeId":101,
"DisplayName":"Engineering",
"ParentIdentifier":0,
"SubCategories":[
{
"NodeId":110,
"DisplayName":"Backend Team",
"ParentIdentifier":101,
"SubCategories":[
{
"NodeId":115,
"DisplayName":"Database Unit",
"ParentIdentifier":110,
"SubCategories":null
}
]
},
...
]
},
...
]