我想对 n-ary Tree 数据结构进行折叠。(折叠在 Linq 中又称为聚合)
我设法提出了一个可行的解决方案:
public static R Aggregate<T, R>(T node,
Func<T, IEnumerable<T>> getChildren,
Func<T, IEnumerable<R>, R> aggregator)
{
var childResults = getChildren(node)
.Select(c => Aggregate(c, getChildren, aggregator));
return aggregator(node, childResults);
}
getChildren
是一个定义如何获取给定节点的子节点的函数。它必须为叶节点返回一个空的 IEnumerable。
定义了如何使用当前节点及其子节点的aggregator
结果来处理节点。
该解决方案似乎有效,但存在一些问题:
该算法是递归的,它会炸毁深树的堆栈。
如何重写函数以防止堆栈溢出?该算法是惰性的,但只是一种。
例如,如果aggregator
only 使用Enumerable.First
子节点的结果,则只遍历树的最左边的分支。然而,Enumerable.Last
整个树被遍历,即使计算只需要最右边的分支。
我怎样才能让算法真正变得懒惰?
欢迎使用 F# 解决方案,但首选 C#。