达到基本情况时如何返回值

时间:2019-07-06 05:00:19

标签: c++ recursion greatest-common-divisor

我正在学习一些基本算法,然后遇到了欧几里得算法,找到了两个数字的GCD。

我在纸上理解算法。 有一个重复的代码可以做到这一点

int euclid_gcd(int a, int b){
    int dividend = a>=b ? a : b;
    int divisor = a<=b ? a : b;
    while(divisor!=0){
        int remainder = dividend % divisor;
        dividend = divisor;
        divisor = remainder;
        }
    return dividend; 
}

我对上面的迭代代码非常满意 再有两个递归版本相同的代码

int gcd(int a, int b){
    if(a==b) 
        return a;
    if(a>b) 
        return gcd(a-b,b);
    return gcd(a,b-a);
}

这是行中最小的一个]

int gcd(int a, int b){ 
    if (a == 0) 
        return b; 
    return gcd(b % a, a);
} 

根据我对递归的理解,在递归中,我们尝试使用已知的答案(基本案例)找到复杂问题的答案(通用案例)

随着递归调用的堆积,从本质上讲,我们将解决一些更简单的问题,直到基本情况发生为止。基本情况返回一个值,由于返回了该值,所有堆叠子问题的答案开始冒泡到原始函数调用,最后我们得到了问题的答案。

我不了解上面的函数调用如何使用基本情况返回的值

这是我尝试空运行上面的代码(第三步)。函数调用是

gcd(20,8);

gcd(20,8)-> gcd(8,20)-> gcd(4,8)-> gcd(0,4)

现在我们通过函数调用gcd(0,4)

它返回了4

现在,上一个函数调用gcd(4,8)如何使用4

我们没有在任何变量中“捕获”返回的值,那么该值究竟发生了什么,最终答案(在这种情况下为4)如何起泡并由原始函数调用返回?

2 个答案:

答案 0 :(得分:2)

考虑以下示例:

int functionA() {
    return functionB();
}

此代码将调用functionB,并将functionB的结果直接返回给functionA的调用者,而无需对其进行操作。相当于写:

int functionA() {
    int toReturn = functionB();
    return toReturn;
}

正如您所说的那样,functionA中显式定义的变量“未捕获” functionB返回的值。

也许递归使您感到困惑,但是您的问题实际上与递归无关。它对任何函数调用均有效。

答案 1 :(得分:2)

我认为您对递归的理解是正确和完整的。您只需要了解有关 Call Stack 在函数调用中的作用。您可以在网上找到许多帖子来掌握这一概念。在这里,我将为您简要介绍调用堆栈概念。

程序的存储器分为多个段。最重要的两个是 Stack Heap 。在这里,我们将重点放在 Stack

每个局部变量和您调用的每个函数都去了那里。您可以在其中找到有关程序的相关信息,包括调用哪些函数,创建的变量以及更多信息。该内存也由程序而非开发人员管理。堆栈是有序的插入位置。

堆栈是LIFO(后进先出)数据结构。您可以将其视为一盒完美匹配的书籍-您放置的最后一本书是您取出的第一本书。通过使用这种结构,程序可以通过使用两个简单的操作:push和pop轻松管理其所有操作和范围。

enter image description here

要跟踪当前的内存位置,有一个特殊的处理器寄存器,称为堆栈指针。每当您需要保存某些内容(例如变量或函数的返回地址)时,它都会向上推并向上移动堆栈指针。每次退出函数时,它都会从堆栈指针弹出所有内容,直到从函数保存的返回地址为止。

我认为现在您知道递归调用中会发生什么。每个函数在堆栈中都有自己的变量。当一个函数到达其return语句时,将结果压入堆栈,另一个调用该函数的函数将从堆栈中弹出结果。

现在,您知道调用堆栈如何工作。这是理解递归的关键概念。