【问题标题】:Find size of Binary Tree recursively递归查找二叉树的大小
【发布时间】:2015-08-15 08:43:54
【问题描述】:

我已经实现了使用递归查找二叉树大小的函数(参考一本关于数据结构和算法的书)

sn-p 代码如下:

// Returns the total number of nodes in this binary tree (include the root in the count).
public static int size(BinaryTreeNode root) {
    int leftCount = root.left == null ? 0 : size(root.left);
    int rightCount = root.right == null ? 0 : size(root.right);
    return 1 + leftCount + rightCount;
}

而且它也有效。 但是我无法理解 leftCount 和 rightCount 元素是如何在递归函数调用之间增加的?不应该像下面这样:

// Returns the total number of nodes in this binary tree (include the root in the count).
public static int size(BinaryTreeNode root) {
    int leftCount = 0;
    int rightCount = 0;
    leftCount = leftCount + (root.left == null ? 0 : size(root.left));
    rightCount = rightCount+ (root.right == null ? 0 : size(root.right));
    return 1 + leftCount + rightCount;
}

由于某种原因,对于下面的二叉树,这两个函数产生相同的结果(7,这是正确的)。

【问题讨论】:

  • 您的第二个版本与第一个版本完全相同-您不会神奇地多次调用size(root.left)(并且正确)-您调用它一次,但是当您调用相同的函数时再次,它被称为递归 - 想象一下你正在调用这个函数的一个新实例(使用其他参数等)......所以当你最终调用它第二个,第三个,......时间root当然@ 987654327@ 将发生变化,leftCount 将是一个新变量(顺便说一句:这会破坏更大的树的堆栈)
  • Carsten,正如我的问题所说,我理解它是一个递归调用。我的问题是为什么选项 1 有效。如果递归调用就像内存中的不同方法调用一样,返回值是如何添加的?
  • 无意冒犯,但我认为您实际上并不了解它是如何工作的 - 返回值得到返回,然后您将它们添加到最后一行
  • 让我们看看你的例子:首先是root = 1(节点不是数字——我希望你明白)然后你计算size (2) next(再次是节点)——现在你得到一个新的带有root=2 的实例现在就在你身边调用size(4),这里没有左/右孩子,所以你返回return 1+0+0,你最终进入root=2 的实例 - 现在你做size(5) = 1+0+0,最后是@ 987654336@ ...与size(3)相同,最后size(1) = 1+3+3为您的最终答案....
  • @Carsten 没有冒犯。我是来学习的。你的第三条评论很有帮助。尽管经过几次尝试,我还是在纸上做了同样的事情。你能把你的解释作为答案吗?这对其他人也有帮助。

标签: recursion data-structures binary-tree


【解决方案1】:

让我尝试通过使用单步执行您的代码来解释它是如何工作的 你展示的二叉树。

您首先使用根节点 (1) 调用 size。它的左孩子 (2) 不是 null,因此您使用 2 调用 size。它的左孩子 (4) 不是 null,因此您使用 4 调用 size。现在,4 的左边是null,所以你将leftCount 设置为04的右边也是null,所以你将rightCount设置为0。然后你将1 + 0 + 0,也就是1,返回给调用函数,也就是节点2的那个。因此,在使用节点 2 调用的函数中,leftCount 设置为 1。现在,我们检查 2 的右孩子,它不是 null,所以我们用它的右孩子 (5) 调用 size。同样,5 没有左子和右子,因此leftCountrightCount 都设置为0,并且函数返回1 + 0 + 0。一旦对 2 右侧的size 的调用返回1rightCount 将设置为1。此时,用2调用的函数返回1 + 1 + 1,即3。因此,对 1 左侧的 size 的调用返回 3,然后我们使用 1 的右子节点调用 size (3 )。使用节点 3size 的调用与我们在使用节点 2 的调用中看到的完全相同,因此返回了 3 的计数。最后,与节点1的原始调用,返回1 + 3 + 3,即7

如果您想要更直观的解释,我制作了一个视频(YouTube 上的find size of binary tree),我首先解释了在高层次上查找大小的过程,然后显示代码,并运行代码步骤- 通过一个示例逐步说明(通过为每个函数调用中的变量值填充一个表,因此很容易看到递归是如何展开的)。

【讨论】:

    【解决方案2】:

    原始代码看起来是正确的,并且正在返回正确的答案。您的可选代码更加冗长 - 它的工作原理相同。记住 leftCount 和 rightCount 是每个递归调用的独立变量。

    我唯一的建议是将传递给 size() 函数的参数名称从根更改为节点。这样就清楚了,同样的函数可以对根节点以外的节点进行操作,递归变得更容易理解了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 2016-07-24
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 2016-04-19
      • 2014-03-29
      • 1970-01-01
      相关资源
      最近更新 更多