我试图了解这个递归函数中发生了什么。它反转了一个String,但我不太明白这些单独的返回调用最后是如何组合成一个字符串的。
def reverse(string: String): String = {
if (string.length() == 0)
return string
return reverse(string.substring(1)) + string.charAt(0)
}
我已经通过添加print语句分析了这个功能,虽然我有点理解它是如何工作的(从概念上讲),我不明白,嗯...... 它是如何的。< / p>
例如,我知道每个递归循环都会将事物推入堆栈。
所以,我希望reverse("hello")
成为一堆
o
l
l
e
h
但它必须比那更复杂,因为递归调用是return reverse(string.substring(1)) + string.charAt(0)
。实际上是堆栈
o,
l, o
l, lo
e, llo
H, ello
?
如何将其变成我们期望的单个字符串?
答案 0 :(得分:6)
堆栈包含所有局部变量,以及递归出现的表达式中的任何临时结果(尽管那些被推送到堆栈上,即使没有递归,因为JVM是一个堆栈机器),当然,这一点代码执行应该在返回时恢复。
在这种情况下,递归调用是整个表达式(也就是说,在它出现的表达式上reverse
之前没有计算任何内容)。所以除了代码指针之外唯一的东西是string
。在最深层次的递归中,堆栈将如下所示:
level string
5 (empty string)
4 o
3 lo
2 llo
1 ello
0 hello
因此,当对级别5的调用返回时,级别4将完成计算reverse
所属的表达式reverse(string.substring(1)) + string.charAt(0)
。 reverse(string.substring(1))
的值为空字符串,string.charAt(0)
的值为o
(因为第4级string
的值为o
)。结果是o
,返回。
在第3级,它将第4级(o
)的返回值与string.charAt(0)
的{{1}}连接,其string
等于lo
,即l
,结果为ol
。
在第2级,它将ol
与l
连接,并提供oll
。
第1级将oll
与e
连接,并返回olle
。
等级0,最后,将olle
与h
连接,并将olleh
返回给其来电者。
最后一点,当进行调用时,推入堆栈的内容是代码和参数的返回点。所以hello
是reverse
的参数,由reverse
的调用者推送到堆栈上。
答案 1 :(得分:6)
使用substitution model解决问题:
reverse("hello") =
(reverse("ello") + 'h') =
((reverse("llo") + 'e') + 'h') =
(((reverse("lo") + 'l') + 'e') + 'h') =
((((reverse("o") + 'l') + 'l') + 'e') + 'h') =
(((((reverse("") + 'o') + 'l') + 'l') + 'e') + 'h') =
((((("" + 'o') + 'l') + 'l') + 'e') + 'h') =
(((("o" + 'l') + 'l') + 'e') + 'h') =
((("ol" + 'l') + 'e') + 'h') =
(("oll" + 'e') + 'h') =
("olle" + 'h') =
"olleh"
答案 2 :(得分:0)
有关如何改进代码的一些提示:
单行功能的最后一个版本:
def reverse(s:String):String = if(s.size == 0)s else reverse(s.tail)+ s.head