【发布时间】:2019-07-06 05:00:19
【问题描述】:
我正在学习一些基本算法,然后我遇到了欧几里得算法来找到两个数字的 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)如何冒泡并由原始函数调用返回?
【问题讨论】:
-
“我们没有‘捕捉’任何变量中的返回值 [...]” 不,但是你正在“捕捉”它在您的
return gcd(b % a, a);语句中,它实际上是说“调用此函数,获取返回的值,并将其用作我自己的返回值(或者换句话说,“转发”返回值)。” -
"根据我对递归的理解,在递归中,我们尝试使用我们知道的答案(基本情况)来找到复杂问题(一般情况)的答案" -不,你太过分了。
-
@Cornstalks 明白了,所以 gcd(20,8) 称为 gcd(8,20),gcd(8,20) 称为 gcd(4,8),gcd(4,8) 称为 gcd( 0,4)。 gcd(0,4) 将 4 返回给它的调用者,然后 4 被所有这些函数返回给它们上面的调用者。知道了。谢谢
-
在每次递归调用之前添加
std::cout将映射您正在发生的事情并帮助您可视化流程。当你返回一个值时,你就完成了。当你返回一个函数时,控制只是在带有新参数的新函数中获得。它一直持续到您返回一个值。例如,添加std::cout << a << " == " << b << " - returning " << a << '\n';或,例如std::cout << a << " > " << b << " - returning gcd(a-b,b)\n";等...应该可以解决问题。
标签: c++ recursion greatest-common-divisor