C# C语言中的函数遍历树#

C# C语言中的函数遍历树#,c#,linq,functional-programming,C#,Linq,Functional Programming,考虑c#,遍历中的以下扩展方法: IEnumerable<T> Traverse<T>( this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse ); 显然,将父属性添加到节点会使问题变得微不足道。相反,我希望以某种方式在函子中构建父字符串。我不认为这在C++中会太难,但是我不知道如何在C语言中实现。有什么

考虑c#,遍历中的以下扩展方法:

IEnumerable<T> Traverse<T>( this IEnumerable<T> source, 
                              Func<T, IEnumerable<T>> fnRecurse );

显然,将父属性添加到节点会使问题变得微不足道。相反,我希望以某种方式在函子中构建父字符串。我不认为这在C++中会太难,但是我不知道如何在C语言中实现。有什么想法吗?

我认为诀窍就是不要传递
节点
类型。而是向下传递
节点
,它是限定路径。比如说

var node = GetTheStartNode();
var start = new { Path = node.Name; Node = node };
var paths = 
   start
     .Traverse( x => x.Node.Children.Select(
        c => new { .Path = x.Path + ":" c.Name; .Node=c) )
     .Select(x => x.Path);

我认为在找到要查找的节点之前,如果不存储父指针,就无法避免搜索树

你将从根开始。测试当前节点是否匹配。如果是匹配项,则返回节点或仅返回名称(作为这一元素的列表)。否则,如果这是叶节点,则返回null。如果不是叶,则遍历其子节点,如果子节点返回非空值,则将当前节点前置到列表并返回该值


从原始调用返回时,null表示未找到匹配项。否则,您将按顺序排列节点列表。

最清晰、最可重用的解决方案:

创建枚举所有可能路径的通用方法:

static IEnumerable<IEnumerable<T>> ComputePaths<T>(T Root, Func<T, IEnumerable<T>> Children) {
    yield return new[] { Root };
    foreach (var Child in Children(Root)) 
        foreach (var ChildPath in ComputePaths(Child, Children)) 
            yield return new[] { Root }.Concat(ChildPath);            
}

我只是输入了完全相同的答案:)(除了你不需要C#中的“With”:@Tony,很好地理解了With。每天使用4种语言不利于连贯性,因此回答:)@Tony,当你切换回JonYup时,twitter风格的评论会显得非常有趣。我“期待”一大堆元问题,问托尼为什么也改了名字。。。
var node = GetTheStartNode();
var start = new { Path = node.Name; Node = node };
var paths = 
   start
     .Traverse( x => x.Node.Children.Select(
        c => new { .Path = x.Path + ":" c.Name; .Node=c) )
     .Select(x => x.Path);
static IEnumerable<IEnumerable<T>> ComputePaths<T>(T Root, Func<T, IEnumerable<T>> Children) {
    yield return new[] { Root };
    foreach (var Child in Children(Root)) 
        foreach (var ChildPath in ComputePaths(Child, Children)) 
            yield return new[] { Root }.Concat(ChildPath);            
}
    // All paths
    var Paths = ComputePaths(Test, x => x.Children);

    // Compute string representation 
    var StrPaths = from p in Paths select string.Join(":", p.Select(t => t.Name).ToArray());

    foreach(var p in StrPaths)
        Console.WriteLine(p);