这个递归函数如何工作?

时间:2014-04-28 00:55:13

标签: c++ c recursion

可能是一个非常基本的问题,但我一直坚持下去。我正在尝试运行以下递归函数:

   //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!";
    }
}

5 个答案:

答案 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

ImmediateOutput

根本原因将是触发更多递归调用的返回值之和。

在递归树的第2级重复每个分支上重复 a b 的原始值...

diagram

答案 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);