我有如下方法,该方法搜索集合并递归评估条件:

public static bool Recurse(this INodeViewModel node, Func<INodeViewModel,bool> predicate)
{
   INodeViewModel currentNode = node;

   return predicate(currentNode) || node.Children.Select(x => Recurse(x, predicate)).Any(found => found);
}

或者,可以使用堆栈来实现此目的,以避免如下所示的递归:
public static bool UsingStack(this INodeViewModel node, Func<INodeViewModel, bool> predicate)
{
   var stack = new Stack<INodeViewModel>();
   stack.Push(node);

   while(stack.Any())
   {
       var current = stack.Pop();

       if (predicate(current))
           return true;

       foreach (var child in current.Children)
       {
           stack.Push(child);
       }
   }
   return false;
}

我的问题是,与递归版本相比,当树的深度较大时,堆栈版本是否会提供性能优势?

最佳答案



是的。当树的深度很大时,递归版本比迭代版本无限慢。这是因为递归版本将破坏调用堆栈,导致无法阻止的堆栈外空间异常,并在返回 bool 值之前终止程序。迭代版本在堆空间用完之前不会这样做,并且堆空间可能比栈空间大数千倍。

完全不给出结果显然比在任何有限的时间内给出结果都更糟糕。

但是,如果您的问题确实是“当树很深时堆栈版本是否有任何好处,但不会那么深以至于炸毁堆栈”,那么答案是:

您已经用两种方法编写了程序。运行它并找出答案。 不要在互联网上显示两匹马的随机陌生人,而是问哪个更快。比赛他们,然后您就会知道。

另外:我倾向于通过编写遍历并产生每个元素的方法来解决您的问题。如果您可以编写IEnumerable<INode> BreadthFirstTraversal(this INode node)IEnumerable<INode> DepthFirstTraversal(this INode node)方法,则无需编写自己的搜索。您可以在要搜索的时候说node.DepthFirstTraversal().Where(predicate).FirstOrDefault()

关于c# - 深度优先搜索的递归方法与堆栈,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15684330/

10-11 08:21