C# 如何执行递归搜索?

C# 如何执行递归搜索?,c#,linq,design-patterns,recursion,tree,C#,Linq,Design Patterns,Recursion,Tree,我有一个任务类,它可以有相同类型的子任务 public class Task { public DateTime Start { get; set;} public DateTime Finish { get; set;} public List<Task> Tasks {get; set;} public DateTime FindTaskStartDate(Task task) {} } 公共类任务 { 公共日期时间开始{get;set;} 公共日期时间完成

我有一个任务类,它可以有相同类型的子任务

public class Task
{
  public DateTime Start { get; set;}
  public DateTime Finish { get; set;}
  public List<Task> Tasks {get; set;}
  public DateTime FindTaskStartDate(Task task)
  {}
}
公共类任务
{
公共日期时间开始{get;set;}
公共日期时间完成{get;set;}
公共列表任务{get;set;}
公共日期时间FindTaskStartDate(任务)
{}
}
我应该如何执行递归搜索(可能是linq)来查找具有最早开始日期的任务

我最初的方法涉及太多的for循环,结果变得有点混乱,并迅速失控。这是我的第二次尝试:

public DateTime FindTaskStartDate(Task task)
{
    DateTime startDate = task.Start;

    if(task.HasSubTasks())
    {
        foreach (var t in task.Tasks)
        {
            if (t.Start < startDate)
            {
                startDate = t.Start;

                if (t.HasSubTasks())
                {
                    //What next?
                    //FindTaskStartDate(t);
                }
            }
        }
    }

    return startDate;
}
public DateTime FindTaskStartDate(任务)
{
DateTime startDate=task.Start;
if(task.HasSubTasks())
{
foreach(task.Tasks中的var t)
{
如果(t.开始<开始日期)
{
起始日期=t.开始;
if(t.HasSubTasks())
{
//接下来呢?
//FindTaskStartDate(t);
}
}
}
}
返回起始日期;
}
有没有更好的办法来解决这个问题


谢谢你说得对,递归是正确的方法。像这样的方法应该会奏效:

public DateTime FindTaskStartDate(Task task)
{
    DateTime startDate = task.Start;

    foreach (var t in task.Tasks)
    {
        var subTaskDate = FindTaskStartDate(t);
        if (subTaskDate < startDate)
            startDate = subTaskDate;
    }

    return startDate;
}

若您希望对所有项目执行其他任务,那个么将树上的迭代和搜索分离可能是有益的。也就是说,如果在树项上实现IEnumerable,则可以使用LINQ查询搜索所需的任何内容,或对树中的所有任务执行其他操作。
看看有什么方法可以做到这一点。

斯维克的解决方案很好,但我想我应该补充一些更一般的建议。似乎您还不熟悉编写递归方法,并且在这方面有点困难。编写递归方法的最简单方法是严格遵循以下模式:

Result M(Problem prob)
{
    if (<problem can be solved easily>)
        return <easy solution>;
    // The problem cannot be solved easily.
    Problem smaller1 = <reduce problem to smaller problem>
    Result result1 = M(smaller1);
    Problem smaller2 = <reduce problem to smaller problem>
    Result result2 = M(smaller2);
    ...
    Result finalResult = <combine all results of smaller problem to solve large problem>
    return finalResult;
}
要使递归工作,需要三件事:

  • 问题必须在每次递归时变得更小
  • 问题最终必须变得非常小,以至于不需要递归就可以解决
  • 这个问题必须通过把它分解成一系列更小的问题,解决每一个问题,并结合结果来解决

如果你不能保证这三件事,那么就不要使用递归解决方案。

这正是我写的,尽管subTaskDate可能应该是DateTime:)类型@Ryan Gibbons:你可以在不指定实际类型的情况下使用,它可以正常工作。它的类型是隐式确定的。@Bernard:是的,但我喜欢显式定义它,尤其是在进行比较时。IMO使代码更具可读性,并且您不需要依靠编译器来确定类型,也不需要进行奇怪的比较。当然,这不应该发生。@Ryan Gibbons:我也更喜欢直言不讳。:)关于隐式与显式的问题,回答得很好。我还是一直喜欢显式的。做递归搜索的最好方法是。。。当然,对于第三个先决条件,对于某些问题,序列可能永远不会有多个元素。例如不可变列表的长度:
int length{get{return this.IsEmpty?0:this.Tail.length+1;}}
Result M(Problem prob)
{
    if (<problem can be solved easily>)
        return <easy solution>;
    // The problem cannot be solved easily.
    Problem smaller1 = <reduce problem to smaller problem>
    Result result1 = M(smaller1);
    Problem smaller2 = <reduce problem to smaller problem>
    Result result2 = M(smaller2);
    ...
    Result finalResult = <combine all results of smaller problem to solve large problem>
    return finalResult;
}
int Depth(Tree tree)
{
    // Start with the trivial case. Is the tree empty?
    if (tree.IsEmpty) return 0;
    // The tree is not empty. 
    // Reduce the problem to two smaller problems and solve them:
    int depthLeft = Depth(tree.Left);
    int depthRight = Depth(tree.Right);
    // Now combine the two solutions to solve the larger problem.
    return Math.Max(depthLeft, depthRight) + 1;
}