考虑这段代码(引用自geeksforgeeks.org,作者Tushar Roy),如果从根到叶的路径具有总和为指定值的键,它会计算true或false:
bool hasPathSum(struct node* node, int sum)
{
/* return true if we run out of tree and sum==0 */
if (node == NULL)
{
return (sum == 0);
}
else
{
bool ans = 0;
/* otherwise check both subtrees */
int subSum = sum - node->data;
/* If we reach a leaf node and sum becomes 0 then return true*/
if ( subSum == 0 && node->left == NULL && node->right == NULL )
return 1;
if(node->left)
ans = ans || hasPathSum(node->left, subSum);
if(node->right)
ans = ans || hasPathSum(node->right, subSum);
return ans;
}
}
在这段代码中,作者在对变量ans的赋值中使用了逻辑OR运算符,以避免用false覆盖true返回。我已将代码重构为:
int hasPathSum(Treelink tree, int sum){
if ( !tree ) { //succesful path found
return (sum == 0);
} else {
sum -= tree->item;
if ( (sum == 0) && (!tree->left && !tree->right))
return 1;
return hasPathSum(tree->left, sum) || hasPathSum(tree->right, sum);
}
}
尽管在这种情况下使用临时变量和/或逻辑OR运算符显然可以有效地防止递归返回的覆盖,但在递归调用中携带值的最佳方法是什么?
编辑
相反,让我们考虑一个稍微人为的例子;给定一个顺序不正确的二叉树(例如,key 100作为根,左子键为5,右子键为2),从树中递归找到最小键。我会天真地这样处理:
免责声明:已编写但未编译。
int findMin(Tree tree, int min) {
if (!tree) return 0; //defensive check
if ( tree->item < min && (tree->left || tree->right) ) {
//Can go deeper and reestablish the min in both directions
if ( tree->left )
min = findMin(tree->left, tree->item);
if ( tree->right )
min = findMin(tree->right, tree->item);
} else if ( tree->item >= min && (tree->left || tree->right ) ) {
//can go deeper but should not reestablish the min
if ( tree->left )
min = findMin(tree->left, min);
if ( tree->right )
min = findMin(tree->right, min);
} else {
return min; //return min's final value
}
}
它大概会通过findMin(testTree, testTree-
tmpmin = findMin(tree->left);
min = (min < tmpmin) ? min : tmpmin;
我们也可能有两个单独的变量(毕竟这是一个二叉树),它们指定左min和右min,并且只返回这两个变量中的min。在这些情况下,我仍在使用某种临时变量来承载其原始调用方。最终,我对设计递归算法时避免这些类型错误的通用启发式很好奇。
编辑:我误解了原来的问题,所以福库的回答更贴切。
C(和大多数其他语言)中的逻辑or运算符执行所谓的短路:一旦找到一个正确的操作数,它就会停止计算操作数。所以如果hasPathSum(树-
这个问题有更详细的解释。它是为Java编写的,但C中的运算符的工作方式相同。
这里是没有优化的原始示例。您将看到算法现在更加清晰了。
bool hasPathSum(struct node* node, int sum)
{
/* return true if we run out of tree and sum==0 */
if (node == NULL)
return (sum == 0);
/* otherwise check both subtrees */
int subSum = sum - node->data;
return hasPathSum(node->left, subSum) || hasPathSum(node->right, subSum);
}
关于实际问题——如何在数据结构中对数据没有约束的这种递归中返回值。返回子树(或您实际查看的任何数据结构)的当前最小值工作得很好。
只需考虑问题,而不考虑实际的数据结构。
current = useful_start_value
for value in data:
if binaryOp(current, value):
current = value
因此,对于每个值,都必须根据当前数据对其进行测试。对于findMin函数,这将生成以下代码。我已经适应了使用原始数据结构。
int findMin(struct node* node, int min) {
if (!node) return min;
if (node->data < min)
min = node->data;
int leftMin = findMin(node->left, min);
if(leftMin < min)
min = leftMin;
int rightMin = findMin(node->right, min);
if(rightMin < min)
min = rightMin;
return min;
}
这样写的话,您还可以清楚地看到访问节点的实际顺序。
我的一般建议是:
我上传了一个完整的工作示例,其中包含用于测试和生成测试树的附加功能。
问题内容: 是否可以通过java的辅助函数保留信息,而无需使用静态变量。 例如, 也就是说,我想更新变量v而不丢失每个递归情况的信息,而不必访问函数外部的变量。 问题答案: 忘记所有告诉您声明属性或在每次递归调用中更新可变对象的答案。在真正的功能性递归样式中,您可以通过将信息作为参数和/或返回类型传递来“保留”信息。 让我用一个简单的示例进行说明,假设您要递归地计算中的元素之和。在这里, 状态 (
我有一个递归函数,它会重复这个函数,直到不满足if条件,然后输出一个整数。但是,此函数之外需要整数的函数正在接收一个单位。我应该如何修改代码以返回int? 这就是整个程序 }
我正在编写一个递归函数,如下所示: 此函数用于接收员工并查找其管理者。如果找到管理器,则将管理器id推送到数组中($)- 所以我的问题是,如果我不在第6行返回递归调用(这是-
我很困惑为什么我写的这个DFS算法没有访问我图中的最终顶点。下面是代码: 图/顶点类 主类 调用DFS_Recursive()的结果是: 我已经使用了IntelliJ调试器,当算法到达顶点C时,堆栈上仍然有剩余的调用,以便它检查E的邻接列表中任何剩余的未访问顶点。然而,在这一点上,它只返回结果ArrayList,其余的递归调用被忽略。 有没有关于发生了什么以及如何修复的想法?
问题内容: 我有一个计算税金的函数。 我不明白为什么它不能停止递归。 问题答案: 在您的职能部门中: 您没有从函数或设置中返回值。当您不返回任何内容时,返回值为。 也许,您想要这样: