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