可能是一个非常基本的问题,但我一直坚持下去。我正在尝试运行以下递归函数:
//If a is 0 then return b, if b is 0 then return a,
//otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)
但它只是陷入了无限循环。任何人都可以帮助我运行该代码并解释该函数究竟是如何工作的吗?我建立了各种递归功能,没有任何问题,但这个只是在我脑海中钻了一个洞。 感谢。
这是我尝试做的事情:
#include<iostream>
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
int main()
{
if (46 == myRec(100, 100)) {
std::cout << "It works!";
}
}
答案 0 :(得分:6)
好吧,让我们在心理上跟踪一下:
Starting with a, b (a >= 2 and b >= 2)
myRec(a/2, 2*b) + something
something + myRec(2*a', b'/2)
替换a / 2代替&#39;我们得到myRec(2*(a/2), (b*2)/2)
,这正是我们开始的地方。
因此,我们永远无法到达任何地方。
(请注意,我在这里省略了一些舍入,但你应该很容易看到,通过这种舍入,你只会将a
向下舍入到最近的偶数,此时它将永远在那个数字和那个数字的一半)
答案 1 :(得分:2)
所以 MyRec(2,2) = MyRec(1,4)+ MyRec(4,1)
并且MyRec(1,4)= MyRec(.5,8)+ MyRec(2,2)
所以 MyRec(2,2) = MyRec(.5,8)+ MyRec(2,2) + MyRec(4,1)
糟糕。
(.5实际上是零。但无关紧要。关键是该函数不会因大量可能的输入而终止。)
答案 2 :(得分:2)
我认为你缺少一些案例逻辑。我在C年前的最后一个程序,所以如果错误,请更正我的语法。假设小于1的数字将自动转换为零......
#include<iostream>
int myRec(int a, int b){
// Recurse only if both a and b are not zero
if (a!=0 && b!=0) {
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
// Otherwise check for any zero for a or b.
else {
if (a==0){
return b;
}
if (b==0){
return a;
}
}
}
<强>更新强>
我几乎忘记了C在返回 ...
上的工作原理int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
VBA相当于显示变量状态的一些更改
Private Function myRec(a As Integer, b As Integer, s As String) As Integer
Debug.Print s & vbTab & a & vbTab & b
If a = 0 Then
myRec = b
End If
If b = 0 Then
myRec = a
End If
If a <> 0 And b <> 0 Then
myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
End If
End Function
Sub test()
Debug.Print myRec(100, 100, "T")
End Sub
在Excel中运行测试会给出这一点(因为它超出了Excel的一小部分):
T: Top | L: Left branch in myRec | R: Right branch in myRec
根本原因将是触发更多递归调用的返回值之和。
在递归树的第2级重复每个分支上重复 a 和 b 的原始值...
答案 3 :(得分:1)
扩展gha.st的答案,将函数的返回值视为表达式的总和,而不必担心任何代码。
首先,我们从myRec(a,b)开始。我们只是表达为(a,b),以便更容易阅读。
当我走下每一行时,每个表达式都是等价的,不考虑a = 0或b = 0的情况。
(a,b)= (a / 2,2b)+(2a,b / 2)= (a / 4,4b)+(a,b)+(a,b)+(4a,b / 4)
现在,我们看到在表达式的非终止点,计算(a,b)需要先计算(a,b)。
这样的问题的递归是有效的,因为参数通常倾向于基本情况&#39;递归停止。一个很好的例子是对列表进行排序;您可以递归地对列表的一半进行排序,直到作为输入给出的列表具有&lt; = 2个元素,这在没有递归的情况下是微不足道的。这称为mergesort。
但是,你的myRec函数没有基本情况,因为对于非零a或b,必须在某个时刻将相同的参数传递给函数。这就像尝试对列表进行排序一样,其中一半列表的元素与整个列表一样多。
答案 4 :(得分:0)
尝试用以下代码替换递归调用:
返回myRec(a / 2,b / 3)+ myRec(a / 3,b / 2);