【发布时间】:2016-08-21 00:32:57
【问题描述】:
我正在使用以下代码对二叉树进行前序遍历:
public void PreorderTraversal(Action<BinaryTreeNode<T>> act) {
Action<BinaryTreeNode<T>> InnerTraverse = null;
InnerTraverse = (node) => {
if (node == null) return;
act(node);
InnerTraverse(node.Left);
InnerTraverse(node.Right);
};
InnerTraverse(this.Root);
}
从性能的角度来看,这种使用本地定义的 lambda 在树上递归的方法是否比将 InnerTraverse 函数简单地定义为 BinaryTree 类上的一个方法(这是定义 PreorderTraversal 函数本身的位置)更差?
【问题讨论】:
-
“复制”怎么办?任何闭包捕获变量都会导致隐藏闭包类的新实例。对于方法的每次调用都是如此,甚至对于在循环的语句块中找到的闭包也是如此。您担心哪种重复?你看过编译的 IL,例如通过 ildasm.exe,更好地了解编译代码中发生了什么?你做了什么研究?我不明白你会认为什么是“负责任的”和“幼稚的”。请提高您问题的清晰度。
-
@PeterDuniho 本质上,我想知道以这种方式使用 lambda 相对于在类级别简单地定义两个函数是否幼稚。我会改写这个问题。我可以衡量性能,但我不清楚使用 lambda 与类方法的含义。
-
当然,不需要使用 lambda 表达式或任何类型的委托来正确遍历二叉树。因此,如果这是您的主要问题,那么是的……您发布的代码是错误的方法。在可能的情况下,应始终选择更简单的实现。具体细节可能会根据您的二叉树数据结构而有所不同;如果您需要有关遍历实现的具体帮助,您应该包含一个好的minimal reproducible example。
-
@PeterDuniho 我正在探索这种方法来进一步封装遍历代码(而不是在 BinaryTree 类上使用私有方法[实际上是三个,因为有 Inorder 和 Postorder])。最终,我将编写一个非递归函数来完成此任务。这个问题的起源只是为了理解递归使用 lambda 的含义,这不是我以前做过的事情。
-
好吧,
PreorderTraversal()方法(大概)只被调用一次,所以至少你不会多次创建InnerTraverse。但是您根本不需要委托,只需抽象用于每个节点的act委托。在其他场景中,您可能希望抽象出如何检索左右节点,这也可以通过传递给遍历方法的委托来完成。根据您迄今为止提供的信息,我认为无需将方法的代码包装在另一个方法中。