我有一个递归函数的例子,我不明白的是事情发生的顺序:
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
该函数何时返回值,在所有过程结束时或每次?
答案 0 :(得分:9)
一种简单的方法可视化递归一般中发生的事情是这样的:
即。如果base = 5且exponent = 3,则调用堆栈是(最后一个元素在顶部):
5*(5*(5*1))
5*(5*(5*power(5, 0)))
5*(5*power(5, 1))
5*power(5, 2)
power(5, 3)
然后每个被调用的函数都有实参,并准备返回一个值(顶部的第一个元素):
5*(5*(5*1))
5*(5*5)
5*25
125
请注意,此处的函数以逆顺序进行计算:首先power(5, 0)
,然后是power(5, 1)
,依此类推。在每次计算之后,堆栈的一个元素被释放(即释放内存)。
希望有所帮助:)
答案 1 :(得分:8)
通常有助于理解像这样的递归函数,就像在代数类中一样。考虑:
power(3, 4)
= 3 * power(3, 3)
= 3 * (3 * power(3, 2))
= 3 * (3 * (3 * power(3, 1)))
= 3 * (3 * (3 * (3 * power(3, 0))))
= 3 * (3 * (3 * (3 * 1)))
= 3 * (3 * (3 * 3))
...
= 81
答案 2 :(得分:6)
这里的关键是power
正在调用自己完全可以调用任何其他函数的方式。所以当它这样做时,它会等待函数返回并使用它的返回值。
所以,如果你这样做
var x = power(10, 2);
您对power
的来电将转到此行:
return base * power(base, exponent - 1)
...并致电power(10, 1)
,等待返回。
对power(10, 1)
的调用当然会到达这一行:
return base * power(base, exponent - 1)
...并致电power(10, 0)
,等待返回。
对power(10, 0)
的调用将返回1
,然后上述#2中的调用将其用于完成其工作并返回10 * 1
= 10
,然后让您在上面#1中的原始通话返回值10 * 10
= 100
。
当试图理解这样的事情时,没有什么比用调试器来浏览代码了。在这个现代世界中,you have plenty to choose from,其中许多可能已经在您的计算机上。
答案 3 :(得分:2)
为了更好地进行可视化,只需将函数调用替换为函数体(例如,可以是伪代码)。
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
power(5, 3)
扩展到此
function power(5, 3) {
// exponent 3 is not 0
// return 5 * power(5, 3-1)
return 5 * function power(5, 2) {
// exponent 2 is not 0
// return 5 * power(5, 2-1)
return 5 * function power(5, 1) {
//exponent 1 is not 0
// return 5 * power(5, 1-1)
return 5 * function power(5, 0){
//exponent 0 is 0
return 1;
}
}
}
}
现在图片清晰了。这一切都变得如下......
// 1
function power(5, 3){
return 5 * function power(5, 2){
return 5 * function power(5, 1){
return 5 * ( function power(5, 0){
return 1;
} )
}
}
}
// 2
function power(5, 3){
return 5 * function power(5, 2){
return 5 * ( function power(5, 1){
return 5 * 1;
} )
}
}
// 3
function power(5, 3){
return 5 * ( function power(5, 2){
return 5 * 5 * 1;
} )
}
// 4
function power(5, 3){
return ( 5 * 5 * 5 * 1 );
}
// 5
5 * 5 * 5 * 1;
答案 4 :(得分:0)
与任何递归函数一样,在计算返回值时会发生特定“实例”的返回。这意味着将计算递归版本。
因此,如果传入4的指数,则某时会执行4个正在执行的函数副本。
答案 5 :(得分:0)
这条线及其分辨率确实让我兴奋不已:
return base * power(base, exponent - 1)
我得到指数递减直到它满足基本情况,但是当你多了多少时 基本乘以递归函数调用,我一直在思考“函数如何通过自身多次(基本争论)?”,它在哪里完全正确,因为调用base * power(base,exponent - 1)并不是'看起来像标准的循环结构。如何调用具有两个论证的函数,它如何知道跳过指数论证并将基数乘以基数?
答案 6 :(得分:0)
从数学角度来看:
让x =基数, 设n =指数
x*x^(n-1) = x^n
因为
x^1*x^n-1=x^n
(类似术语的指数加在一起)
与以下内容相同:
base * base*exponent-1.