递归函数通常遵循“分而治之” -strategy。
要查找的最大列表
max(a, b, c, d)
我们可以分区列表随意,然后找到最大的所有局部最大值:
<=> max(max(a, b), max(c, d))
你的算法选择以下分区:
<=> max(a, max(b, c, d))
对max(b, c, d)
也是如此,导致以下呼叫图:
max(a, b, c, d)
max(b, c, d)
max(c, d)
max(d)
在max(d)
,该算法不会进一步递归。相反,这是基本情况(相当于一个循环的终止条件)。 max(d)
返回d
。现在,我们可以通过最大列表的其余部分的对比给我们的第一价值,通过调用堆栈工作回来的路上
还有很多其他的方法这种想法可以被编码找到总最大。它可以转换为非递归形式
sub maxNum {
my $current_max = pop;
while(@_) {
my $compare = pop;
$current_max = $compare if $compare > $current_max;
}
return $current_max;
}
这比较了与递归解决方案相同顺序的元素。
查找最大值也可以认为是折叠操作(又名reduce
)。我们可以写一个递归函数,它下面的分区:
max(a, b, c, d)
<=> max(max(a, b), c, d)
<=> max(max(max(a, b), c), d)
这看起来相当复杂,但导致一个优雅的解决方案:
sub maxNum {
return $_[0] unless $#_; # return if less than two elems
my ($x, $y) = splice 0, 2, @_; # shift first two elems from @_
my $max = $x > $y ? $x : $y; # select larger
return maxNum($max, @_); # recurse
}
函数调用,其价值立即返回被称为一个尾呼。我们可以通过使用特殊的goto &subroutine
表达式来提高效率。但是,我们必须手动设置参数列表:
sub maxNum {
return shift unless $#_; # base case: return on one argument
my ($x, $y) = splice 0, 2, @_; # take the first two elems from start
unshift @_, $x > $y ? $x : $y; # put the larger one back there
goto &maxNum; # recurse with tail call
}
这是如何初始调用的? – 2013-05-07 15:45:21
你对递归的理解是错误的。之前对递归函数的调用基本上阻塞,直到所有后来的递归调用完成。 – chepner 2013-05-07 16:25:54