【问题标题】:Explanation for reverse_string recursive functionreverse_string 递归函数说明
【发布时间】:2015-02-17 17:57:52
【问题描述】:
无论我用 Python 可视化工具运行它多少次,我都无法弄清楚这段代码是如何工作的;有人可以告诉我以下代码的递归是如何工作的吗?
def reverse_strings(string):
if len(string) == 0: return ''
else: return reverse_strings(string[1:]) + string[0]
reverse_strings('hello')
我自己写的,它可以工作,但我不知道它是如何工作的。我知道返回递归的工作原理是在递归函数中运行“ello”,但我一生都无法理解它是如何向后打印东西的。
【问题讨论】:
标签:
python
string
recursion
【解决方案1】:
它使用切片将第一个字母连接到末尾,然后将第二个字母传递给剩余的字母再次传递给递归函数。
【解决方案2】:
第一次通话时的string[1:] 是ello string[0] 是h:
第二次递归调用string[1:] -> llostring[0] -> e
第三个string[1:] ->lo string[0] -> l
第四个string[1:] ->o string[0] -> l
5th string[1:] ->"" string[0] -> o
所以reverse_strings(string[1:]) 调用函数在字符串中递归移动,string[0] 从末尾开始连接每个字母,这就是最后返回的内容。
下面的图表可能会有所帮助:
【解决方案3】:
递归的概念是您调用相同的函数,直到遇到基本情况。在您的情况下,基本情况是len(string) == 0,您向调用者返回一个空字符串,这是同一函数reverse_strings的先前版本,但具有不同的参数(通常是更“复杂”函数)。
假设你有这个简单的字符串hi,你的函数会是这样的:
检查是否达到基本情况,如果是,则返回一个空字符串,否则转到下一条语句。由于我们没有空字符串,我们转到下一条语句。
下一条语句调用相同的函数reverse_strings,但参数与第一次运行时不同;实际上,第一次调用它时,您会执行类似reverse_strings('hi') 的操作。在else 中,您使用较小版本的字符串hi 调用该函数,请注意以下语句:return reverse_strings(string[1:]) + string[0] string[1:] 只是i。现在,基本上你有return reverse_strings('i') + string[0]。请注意,string[0] 是 H。在这里,reverse_strings('i'),正如我上面所说,您再次调用您的函数,但使用较小版本的字符串 i。
现在,我们在另一个函数调用中。评估第一条语句if len(string) == 0: return ''。这是真的吗?不,因为len(string) 仍然与0 不同。所以我们传递到下一个语句else: return reverse_strings(string[1:]) + string[0]。现在,请注意我们将再次调用相同的函数。但使用较小的字符串,在本例中为空字符串,因为 string[1:] 的 i 是空字符串。所以我们的电话可以总结为return reverse_strings('') + i。
我们现在处于reverse_strings 的另一个“简化版本”中。第一个语句被评估if len(string) == 0: return ''。这是真的吗?是的,因为请记住,我们的字符串现在是一个空字符串。现在发生的是你返回一个空字符串给调用者,也就是第3点中的函数。
现在,我们刚刚在第 3 点向调用者返回了一个空字符串,所以我们有 return '' + i。 '' + i 只不过是简单的i,您将在指针 3 处返回此函数的调用者,即点 2 处的函数。
1234563 @你刚回来。所以,现在你有了iH,而且你刚刚反转了字符串。
【解决方案4】:
要真正理解这一点,我会用一种声明性的、某种逻辑形式来表达它。
这是你的代码:
1: if len(string) == 0: return ''
2: else: return reverse_strings(string[1:]) + string[0]
我将字符串的第一个元素 (string[0]) 称为 head,其余的 (string[1:]) 称为 tail。如果一个字符串只有 1 个字符长,我们认为它的尾部是空字符串。就该词汇而言,以下是反转字符串含义的规则:
- 空字符串反转为空字符串。
- 任何其他反转的字符串都是其尾部的反转版本,然后是其头部。
例如,abcd,我们应用规则 2,因为规则 1 不适用:
好的,bcd 反转了什么?好吧,我们可以应用相同的规则:
并沿着链条:
-
cd 反转为d 反转,后跟c,
-
d 反转是'' 反转,后跟d,
-
根据规则 1,
'' 反转为 '',因为它是空字符串。
回到这个列表,你会得到:
这是dcba,这就是我们想要的!
了解递归并不容易。尝试用它解决一些其他问题或做一些需要它的练习;这种做法确实有助于理解。