C#中含id/parentId的类对象列表生成树形层级结构的实现问询
解决C#中父子结构列表生成层级路径的问题
嘿,这个需求其实挺常见的——把扁平的父子节点列表转成带层级的路径输出,核心思路就是先把列表构建成树形结构,再递归遍历每个节点生成对应的层级字符串就行。我给你一步步拆解实现:
第一步:定义节点类(或扩展现有类)
首先,我们需要给你的节点类加一个Children属性,方便构建树形结构。如果你的原有类已经有类似属性,直接用就行:
public class TreeNode { public int Id { get; set; } public int ParentId { get; set; } // 新增子节点集合,用于构建树 public List<TreeNode> Children { get; set; } = new List<TreeNode>(); }
第二步:将扁平列表转换为树形结构
我们用字典来快速查找父节点,这样能高效地把每个节点关联到它的父节点下:
public static List<TreeNode> BuildTree(List<TreeNode> flatNodes) { // 用字典存储所有节点,O(1)查找 var nodeDict = flatNodes.ToDictionary(n => n.Id); var rootNodes = new List<TreeNode>(); foreach (var node in flatNodes) { if (node.ParentId == 0) { // ParentId=0是根节点,直接加入根列表 rootNodes.Add(node); } else { // 找到父节点,将当前节点加入父节点的子集合 if (nodeDict.TryGetValue(node.ParentId, out var parentNode)) { parentNode.Children.Add(node); } } } return rootNodes; }
第三步:递归遍历树生成层级路径
接下来写一个递归方法,遍历每个节点,记录当前路径的层级,不足4层的用--补全:
public static List<string> GenerateHierarchyPaths(List<TreeNode> rootNodes) { var paths = new List<string>(); // 递归遍历每个节点,初始路径为空,层级为1 TraverseNode(rootNodes, new List<int>(), paths); return paths; } private static void TraverseNode(List<TreeNode> nodes, List<int> currentPath, List<string> paths) { foreach (var node in nodes) { // 把当前节点ID加入路径 var newPath = new List<int>(currentPath) { node.Id }; // 生成层级字符串:不足4层的用--补全 var pathStr = string.Join(" ", newPath.Concat(Enumerable.Repeat("--", 4 - newPath.Count))); // 添加到结果列表 paths.Add(pathStr); // 递归遍历子节点 TraverseNode(node.Children, newPath, paths); } }
第四步:测试示例验证结果
用你给出的测试数据跑一下:
var flatNodes = new List<TreeNode> { new TreeNode { Id = 1, ParentId = 0 }, new TreeNode { Id = 2, ParentId = 1 }, new TreeNode { Id = 3, ParentId = 1 }, new TreeNode { Id = 4, ParentId = 3 }, new TreeNode { Id = 5, ParentId = 3 }, new TreeNode { Id = 6, ParentId = 2 }, new TreeNode { Id = 7, ParentId = 1 }, new TreeNode { Id = 8, ParentId = 4 } }; var rootTree = BuildTree(flatNodes); var hierarchyPaths = GenerateHierarchyPaths(rootTree); // 输出结果(先打印表头) Console.WriteLine("first - second - third - fourth"); foreach (var path in hierarchyPaths) { Console.WriteLine(path); }
预期输出:
first - second - third - fourth 1 -- -- -- 1 2 -- -- 1 2 6 -- 1 3 -- -- 1 3 4 -- 1 3 4 8 1 3 5 -- 1 7 -- --
一些实用注意点
- 如果你的层级可能超过4层,可以把代码里的
4改成一个可配置的参数(比如传入maxDepth),灵活适配不同的层级需求 - 如果存在孤立节点(找不到对应ParentId的父节点),可以在构建树的逻辑里加个日志提示,避免节点遗漏
- 字典查找的时间复杂度是O(1),整个构建树的过程是O(n),对于100多个节点来说,性能完全不用担心
内容的提问来源于stack exchange,提问作者Sabith
相关产品推荐
相关产品推荐

