【问题标题】:what is the return value of this recursive code means?这个递归代码的返回值是什么意思?
【发布时间】:2021-07-14 13:51:44
【问题描述】:

我无法理解这种递归代码,我该怎么做才能理解这些函数。你能帮我解释一下这个函数的作用吗(一个例子会有很大帮助)。

typedef struct node* Nodeptr;
typedef struct node{
    int key;
    Nodeptr left,right;
}Node;

【问题讨论】:

  • 欢迎来到 SO。请尝试以文本形式提供代码,而不是图像。您可能想阅读Why not upload images of code/errors when asking a question?
  • 如果提供的结构是二叉树并且条件t->left == t->right 仅在两者都是NULL 时为真,则此代码可能有意义。是这样吗?
  • 如果是这样,你能推断出它为叶子节点返回了什么吗?你能推断出它会为非叶节点返回什么吗?
  • 我编辑了我的问题。
  • StackOverflow 是一个成功的社区,部分原因是提问者应该准确地解释他们的问题是什么。这些类型的问题对整个社区以及将来可能遇到您的问题的任何其他读者都很有用。如果我们有 2000 万个问题说“帮助我不明白”,这不仅难以提供有用的答案,而且也难以让其他人受益。

标签: c pointers recursion tree


【解决方案1】:

解释函数没有通用规则。在没有记录的情况下,了解他们的工作需要经验。

在递归函数的情况下,我们可以尝试从函数的基本情况建立一些理解并从那里开始。基本情况或情况是函数不调用自身的情况:它直接产生答案,无需递归。在这个函数中,有两种基本情况。第一个是:

if (!t)
    return NULL;

这是一个小例子:如果函数传递了一个空指针,它返回一个空指针并且不会改变*a

另一个是:

if (t->left == t->right)
{
    *a = t->key;
    return t;
}

作为Eugene sh. notes,这是对叶节点的混淆测试:如果leftright 指向另一个节点,则t->left == t->right 在正确的二叉树中永远不会为真。当且仅当leftright 都是空指针时才成立,因此这是一个叶节点(它没有任何子节点)。

因此,对于叶节点,该函数返回节点 (t) 并将 *a 设置为其键的值。

然后我们有递归的情况:

x = f(t->left, &b);
y = f(t->right, &c);
*a = b>c ? b+t->key : c+t->key;
return b>c ? x : y;

前两行对于二叉树上的递归函数很常见:我们将函数应用于左子树和右子树。 (请注意,如果传递的指针为空,bc(以传递者为准)不会更改(由于上述简单的基本情况),因此它保持其初始化值为零。)

然后*a = b>c ? b+t->key : c+t->key;t-key 添加到bc 中的较大者,并将*a 设置为总和。来自另一个子树的值被忽略。因此,我们正在计算某种最大值。

然后return b>c ? x : y; 返回指向我们使用其值的节点的指针。因此,它会返回一些关于我们从哪里获得最大值的指示。

现在我们知道了树对它下面的一层子树做了什么:它计算当前键的值加上它下面的键的最大值,然后把这个和放入*a。它返回一个指向我们从中获取值的叶节点的指针。

由此,我们可以弄清楚它对两级子树的作用:它计算当前键的值加上它进行的两次调用的最大值。所以它是从两条路径中选择最大和。它返回与它选择的总和相关的指针,它从一个指向叶节点的指针开始。所以函数总是返回一个指向正在使用的路径末尾的叶节点的指针。

总的来说,该函数计算从根到叶的任何路径上的最大总和,并将其放入*a。它返回一个指向路径末尾的叶子的指针。

注意以上假设key 是非负数。如果某些key 值为负数,它们可能会被为空子树计算的零值覆盖。

【讨论】:

  • 非常感谢您的努力和出色的解释。
猜你喜欢
  • 2011-05-28
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多