簡體   English   中英

如何進行遞歸搜索?

[英]How to perform a recursive search?

我有一個Task類,它可以有相同類型的子任務

public class Task
{
  public DateTime Start { get; set;}
  public DateTime Finish { get; set;}
  public List<Task> Tasks {get; set;}
  public DateTime FindTaskStartDate(Task task)
  {}
}

我應該如何執行遞歸搜索(也許linq)以找到具有最早開始日期的任務?

我最初的方法涉及太多的循環,它結束了變得有點亂,並迅速失控。 這是我的第二次嘗試:

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

有什么更好的解決方案可以解決這個問題嗎?

謝謝

Svick的解決方案很好,但我想我會添加一些更一般的建議。 看起來你是編寫遞歸方法的新手並且在那里苦苦掙扎。 編寫遞歸方法的最簡單方法是嚴格遵循以下模式:

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

你需要三件事來做遞歸工作:

  • 每次遞歸時問題都必須變
  • 問題必須最終變得如此之小,以至於無需遞歸就可以解決問題
  • 問題必須通過將其分解為一系列較小的問題,解決每個問題並將結果組合來解決。

如果你不能保證這三件事,那么就不要使用遞歸解決方案

你是對的,遞歸是正確的方法。 這樣的事情應該有效:

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

我刪除了task.HasSubTasks()的檢查,因為它只會使代碼更復雜而沒有任何額外的好處。

如果您發現經常編寫代碼需要遍歷樹中的所有任務,您可能希望使其更加通用。 例如,您可以使用返回IEnumerable<Task>的方法,該方法返回樹中的所有任務。 找到最小的開始日期將非常簡單:

IterateSubTasks(task).Min(t => t.Start)

如果您要對所有項目執行其他任務,則從搜索中分離樹的迭代可能是有益的。 即如果您在樹項上實現IEnumerable,您可以使用LINQ查詢來搜索您想要的任何內容,或者對您樹中的所有任務執行其他操作。 檢查在樹結構上實現IEnumerable以獲取實現方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM