提问人:CF7 提问时间:9/23/2022 更新时间:9/23/2022 访问量:183
C# 将递归替换为 while 循环
C# replace recursive with while loop
问:
我们有一个来自系统的节点树,模型就像Node
Public class Node {
public string Name { get; set; }
public bool HasChildren { get; set; }
public List<Node> Children { get; set; }
}
因此,根据模型,节点树的 JSON 将如下所示:Node
{
"Name": "Root",
"HasChildren": true,
"Children": [
{
"Name": "Node-1",
"HasChildren": true,
"Children": [
{
"Name": "Node-1-1",
"HasChildren": false,
"Children": []
}
]
},
{
"Name": "Node-2",
"HasChildren": true,
"Children": [
{
"Name": "Node-2-1",
"HasChildren": false,
"Children": [
{
"Name": "Node-2-1-1",
"HasChildren": false,
"Children": []
}
]
},
{
"Name": "Node-2-2",
"HasChildren": false,
"Children": [
{
"Name": "Node-2-2-1",
"HasChildren": false,
"Children": []
}
]
}
]
}
...
]
}
现在,我想将每个节点保存在一个扁平化的数组或列表中。要遍历所有节点,我知道我可以递归地获取它们。但是,使用递归会导致大量内存使用。
有没有办法使用循环逻辑,如 、 或逻辑来做同样的事情?while
for
foreach
答:
2赞
SomeBody
9/23/2022
#1
使用此代码,您可以在循环中完成:
List<Node> result = new List<Node> { node };
bool finished = false;
int start = 0;
while(!finished)
{
int end = result.Count;
for(int i = start; i < end; i++)
{
if(result[i].HasChildren)
{
result.AddRange(result[i].Children);
}
}
if(result.Count == start)
{
finished = true;
}
start = end;
}
首先,我们将根节点添加到结果列表中。然后我们进入一个循环,其中有另一个循环。此内部循环遍历上次迭代中添加的所有条目。在第一次迭代中,内部循环仅通过根节点。然后,内部循环将这些节点的所有子节点添加到结果列表中。外部循环将运行,直到内部循环不再添加任何节点。
请注意,它将更改扁平化列表的顺序。节点的子节点不会直接位于其父节点的后面。相反,节点在层次结构中的位置越靠后,该节点在列表末尾的位置就越大。我希望这对你来说没问题,因为你没有写任何关于你喜欢的订单。
在线演示:https://dotnetfiddle.net/Rx67kK
评论
0赞
JonasH
9/23/2022
这种排序可以称为“广度优先”。此外,所有孩子都将被安置在父母的身后,但不会紧随父母的身后。
0赞
CF7
9/27/2022
谢谢你@SomeBody,我确实喜欢这个解决方案和你的解释。它做了我想要实现的目标。再次感谢!
3赞
JonasH
9/23/2022
#2
我的 goto 树迭代器如下所示:
public static IEnumerable<T> DepthFirst<T>(T self, Func<T, IEnumerable<T>> selector)
{
var stack = new Stack<T>();
stack.Push(self);
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in selector(current))
{
stack.Push(child);
}
}
}
称为 .这是泛型的,因此它可以重用于所有不同类型的树表示形式。它也被懒惰地评估。DepthFirst(myRootNode, n => n.Children)
此变体以深度一阶迭代,但将堆栈更改为队列以获得广度一阶是微不足道的。
评论