How to perform a recursive search?

前端 未结 3 778
无人及你
无人及你 2020-12-24 11:03

I have a Task class which can have sub tasks of the same type

public class Task
{
  public DateTime Start { get; set;}
  public DateTime Finish { get; set;}
         


        
相关标签:
3条回答
  • 2020-12-24 11:42

    You're right, recursion is the right approach here. Something like this should work:

    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;
    }
    

    I removed the check for task.HasSubTasks(), because it only makes the code more complicated without any added benefit.

    If you find your often write code that needs to walk all of the tasks in the tree, you might want to make this more general. For example, you could have a method that returns IEnumerable<Task> that returns all the tasks in the tree. Finding the smallest start date would then be as easy as:

    IterateSubTasks(task).Min(t => t.Start)
    
    0 讨论(0)
  • 2020-12-24 11:50

    Svick's solution is fine, but I thought I'd add a bit more general advice. It seems like you are new to writing recursive methods and were struggling a bit there. The easiest way to write a recursive method is to strictly follow a pattern:

    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;
    }
    

    So suppose you want to solve the problem "what is the maximum depth of my binary tree?"

    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;
    }
    

    You need three things to make recursion work:

    • The problem has to get smaller every time you recurse.
    • The problem has to eventually get so small that it can be solved without recursion
    • The problem has to be solvable by breaking it down into a series of smaller problems, solving each one, and combining the results.

    If you cannot guarantee those three things then do not use a recursive solution.

    0 讨论(0)
  • 2020-12-24 11:58

    Separating iteration over tree from search may be beneficial if there are other tasks you want to do on all items. I.e. if you implement IEnumerable over the tree items you can use LINQ queries to search for anything you want or perform other operations on all tasks in you tree. Check out Implementing IEnumerable on a tree structure for a way to do so.

    0 讨论(0)
提交回复
热议问题