C#层级数据遍历需求:调整递归顺序匹配报表打印要求
解决C#层级结构指定顺序遍历问题
需求说明
现有层级结构递归遍历输出为 1->2->4->8->5->3->6->7,需要调整为以下顺序:
- 第一阶段:
1->2->4->5->8 - 第二阶段:
1->3->6->7
层级结构定义
首先完善Hierarchy类(增加父节点引用以支持兄弟节点遍历):
public class Hierarchy { public int Id { get; set; } public int ParentId { get; set; } public Hierarchy Parent { get; set; } public List<Hierarchy> Children { get; set; } = new List<Hierarchy>(); }
构建测试数据
// 构建示例层级结构 var root = new Hierarchy { Id = 1 }; var node2 = new Hierarchy { Id = 2, ParentId = 1, Parent = root }; var node3 = new Hierarchy { Id = 3, ParentId = 1, Parent = root }; var node4 = new Hierarchy { Id = 4, ParentId = 2, Parent = node2 }; var node5 = new Hierarchy { Id = 5, ParentId = 2, Parent = node2 }; var node8 = new Hierarchy { Id = 8, ParentId = 4, Parent = node4 }; var node6 = new Hierarchy { Id = 6, ParentId = 3, Parent = node3 }; var node7 = new Hierarchy { Id = 7, ParentId = 3, Parent = node3 }; root.Children.Add(node2); root.Children.Add(node3); node2.Children.Add(node4); node2.Children.Add(node5); node4.Children.Add(node8); node3.Children.Add(node6); node3.Children.Add(node7);
实现方案
方案1:针对固定结构的简单实现
如果层级结构固定,可以直接硬编码分支处理逻辑,快速得到目标顺序:
public List<int> GetDesiredSequence(Hierarchy root) { var result = new List<int>(); // 第一阶段:遍历1->2->4->5->8 result.Add(root.Id); result.Add(root.Children.First(c => c.Id == 2).Id); var node4 = root.Children.First(c => c.Id == 2).Children.First(c => c.Id == 4); result.Add(node4.Id); result.Add(root.Children.First(c => c.Id == 2).Children.First(c => c.Id == 5).Id); // 遍历node4的子节点 TraverseDepthFirst(node4, result); // 第二阶段:遍历1->3->6->7 result.Add(root.Id); var node3 = root.Children.First(c => c.Id == 3); result.Add(node3.Id); TraverseDepthFirst(node3, result); return result; } // 常规深度优先遍历子节点 private void TraverseDepthFirst(Hierarchy node, List<int> result) { foreach (var child in node.Children) { result.Add(child.Id); TraverseDepthFirst(child, result); } }
方案2:通用化实现(支持动态分支)
如果结构可能变化,可通过同级优先遍历逻辑实现,无需硬编码ID:
public List<int> GetDesiredSequence(Hierarchy root) { var result = new List<int>(); // 第一阶段:处理根节点 + 2分支(同级优先遍历) result.Add(root.Id); var node2 = root.Children.First(c => c.Id == 2); result.Add(node2.Id); // 对node4启用同级优先遍历 TraverseWithSiblingPriority(node2.Children.First(c => c.Id == 4), result, true); // 第二阶段:处理根节点 + 3分支(常规深度优先) result.Add(root.Id); var node3 = root.Children.First(c => c.Id == 3); TraverseWithSiblingPriority(node3, result, false); return result; } // 可切换遍历逻辑的方法:true=先遍历同级兄弟,再遍历子节点;false=常规深度优先 private void TraverseWithSiblingPriority(Hierarchy node, List<int> result, bool prioritizeSiblings) { result.Add(node.Id); if (prioritizeSiblings && node.Parent != null) { // 先遍历当前节点的所有兄弟节点(排除自身) foreach (var sibling in node.Parent.Children.Where(s => s != node)) { result.Add(sibling.Id); // 兄弟节点采用常规深度优先遍历 TraverseWithSiblingPriority(sibling, result, false); } // 再遍历当前节点的子节点 foreach (var child in node.Children) { TraverseWithSiblingPriority(child, result, true); } } else { // 常规深度优先遍历 foreach (var child in node.Children) { TraverseWithSiblingPriority(child, result, false); } } }
测试结果
调用GetDesiredSequence(root)后,输出列表为:[1, 2, 4, 5, 8, 1, 3, 6, 7],完全符合需求。
内容的提问来源于stack exchange,提问作者Zoyeb Shaikh
相关产品推荐
相关产品推荐

