简体   繁体   English

reverse_string递归函数的说明

[英]Explanation for reverse_string recursive function

No matter how many times I run it by Python visualizer, I can't figure out how this code works; 不管我用Python visualizer运行多少次,我都无法弄清楚这段代码是如何工作的。 can someone PLEASE tell me how the recursion of this following code works? 有人可以告诉我以下代码的递归如何工作吗?

def reverse_strings(string):
    if len(string) == 0: return ''
    else: return reverse_strings(string[1:]) + string[0]

reverse_strings('hello')

I wrote it myself, and it works, but I have no idea how it works. 我自己编写了它,并且有效,但是我不知道它是如何工作的。 I know return recursion works by running the "ello" into the recursive function, but I can't for the life of me understand how it's printing things backwards. 我知道返回递归可以通过在递归函数中运行“ ello”来实现,但是我一生都无法理解它是如何向后打印内容的。

The concept of recursion is that you call a the same function until the base case is encountered . 递归的概念是您调用相同的函数,直到遇到基本情况为止 In your case, the base case is when len(string) == 0 , where you return an empty string 在您的情况下,基本情况是len(string) == 0 ,您返回一个空字符串 to the caller, which was a previous version of the same function reverse_strings , but with different parameters (usually a more "complex" function). 到调用方,该调用方是相同功能reverse_strings的先前版本,但具有不同的参数(通常是更“复杂”的功能)。

Suppose you have this simple string hi , your function would behave like this: 假设您有一个简单的字符串hi ,您的函数将如下所示:

  1. Check if the base case is reached, if yes, return an empty string, otherwise go to next statement. 检查是否达到基本情况,如果是,则返回一个空字符串,否则转到下一条语句。 Since we don't have an empty string, we go to the next statement. 由于没有空字符串,因此转到下一条语句。

  2. Next statement calls the same function reverse_strings , but with different parameters than when you call it the first time to run it; next语句调用相同的函数reverse_strings ,但是参数与第一次运行它时不同。 in fact, the first time you call it, you do something like this reverse_strings('hi') . 实际上,第一次调用它时,您会执行类似reverse_strings('hi') In the else , you are calling the function with a smaller version of your string hi , observe in the following statement: return reverse_strings(string[1:]) + string[0] that string[1:] is just i . else ,您正在使用较小版本的字符串hi调用函数,请注意以下语句: return reverse_strings(string[1:]) + string[0]表示string[1:]只是i Now, basically you have return reverse_strings('i') + string[0] . 现在,基本上您已经return reverse_strings('i') + string[0] Note that string[0] is H . 注意string[0]H Here, reverse_strings('i') , as I said above, you are calling your function again, but with a smaller version of your string i . 如我上面所说,在这里, reverse_strings('i')再次调用了函数,但是使用了较小的字符串i

  3. Now, we are inside another function call. 现在,我们在另一个函数调用中。 The first statement if len(string) == 0: return '' is evaluated. if len(string) == 0: return ''的第一条语句被评估。 Is it true? 是真的吗 No, because len(string) is still different from 0 . 否,因为len(string)仍然不同于0 So we pass to the next statement else: return reverse_strings(string[1:]) + string[0] . 因此,我们转到下else: return reverse_strings(string[1:]) + string[0]语句else: return reverse_strings(string[1:]) + string[0] Now, note that we are going to call the same function again. 现在,请注意,我们将再次调用同一函数。 but with a smaller string, in this case, an empty string, since string[1:] of i is an empty string. 但是使用较小的字符串(在这种情况下为空字符串),因为i string[1:]是空字符串。 So our call can be summarised like this return reverse_strings('') + i . 因此,我们的调用可以像下面这样总结: return reverse_strings('') + i

  4. We are now in another "simplified version" of reverse_strings . 我们现在处于reverse_strings另一个“简化版本”中。 The first statement is evaluated if len(string) == 0: return '' . if len(string) == 0: return ''则评估第一条语句。 Is it true? 是真的吗 Yes, because, remember, our string is now an empty string. 是的,因为请记住,我们的字符串现在是一个空字符串。 What happens now is that you return an empty string to the caller, which is the function in the point 3. 现在发生的是,您向调用者返回了一个空字符串,这是第3点中的函数。

  5. Now, we have just returned an empty string to the caller at point 3, so we have return '' + i . 现在,我们刚刚在第3点向调用者返回了一个空字符串,因此我们return '' + i '' + i is nothing else than simply i , which you are going to return to the caller of this function at pointer 3, which is the function at point 2. '' + i就是简单的i ,您将返回到指针3处的函数的调用者,指针3是点2处的函数。

  6. Now, you have just returned i to the caller, specifically you have just returned i to this statement return reverse_strings('i') + string[0] , where string[0] is H and reverse_strings('i') is just i that you have just returned. 现在,您刚刚将i返回给了调用方,特别是您刚刚将i返回给了该语句return reverse_strings('i') + string[0] ,其中string[0]Hreverse_strings('i')只是i你刚回来。 So, now you have iH , and you have just reversed the string. 因此,现在您有了iH ,并且您刚刚反转了字符串。

它使用切片将第一个字母连接到末尾,然后将第二个到其余的字母再次传递到递归函数中。

string[1:] on the first call is ello string[0] is h : 第一次调用时string[1:]ello string[0]h

2nd recursive call string[1:] -> llo string[0] -> e 第二个递归调用string[1:] -> llo string[0] -> e

3rd string[1:] -> lo string[0] -> l 第三string[1:] -> lo string[0] -> l

4th string[1:] -> o string[0] -> l 第四个string[1:] -> o string[0] -> l

5th string[1:] -> "" string[0] -> o 第5个string[1:] -> “” string[0] -> o

So reverse_strings(string[1:]) calls the function recursively moving across the string and string[0] concatenates each letter starting from the end which is what is returned at the end. 因此, reverse_strings(string[1:])调用该函数以递归方式在字符串上移动,并且string[0]将每个字母从末尾开始连接,这是最后返回的内容。

The graph below may help: 下图可能会有所帮助:

递归树

To really understand this, I would express it in a declarative, sort-of logical form. 为了真正理解这一点,我将以一种声明性的逻辑形式来表达它。 Here's your code: 这是您的代码:

1: if len(string) == 0: return ''
2: else: return reverse_strings(string[1:]) + string[0]

I'll call the first element of a string ( string[0] ) its head and the remainder ( string[1:] ) its tail . 我将字符串的第一个元素( string[0] )命名为 ,将其余的( string[1:] )命名为tail If a string is only 1 character long, we consider its tail to be the empty string. 如果字符串只有1个字符长,则我们将其尾部视为空字符串。 In terms of that vocabulary, here are the rules for what it means to reverse a string: 根据该词汇表,以下是反向字符串的含义的规则:

  1. The empty string reversed is the empty string. 反转的空字符串是空字符串。
  2. Any other string reversed is the reversed version of its tail, followed by its head. 任何其他反向的字符串是其尾巴的反向版本,其后跟其头部。

In the case of, for example, abcd , we apply rule 2 since rule 1 doesn't apply: 例如,对于abcd ,我们应用规则2,因为规则1不适用:

  • abcd reversed is bcd reversed, followed by a . abcd reversed是bcd相反,其后是a

Ok, what's bcd reversed? 好的, bcd反转了什么? Well, we can apply the same rule: 好吧,我们可以应用相同的规则:

  • bcd reversed is cd reversed, followed by b . bcd反转是cd反转,后跟b

and down the chain: 下链:

  • cd reversed is d reversed, followed by c , cd反转是d反转,然后是c
  • d reversed is '' reversed, followed by d , d反转为''反转,后跟d
  • '' reversed is '' , by rule 1, because it is the empty string. 根据规则1, '' reversed is '''' ,因为它是空字符串。

Going back up this list, you get: 返回此列表,您将获得:

  • '' followed by d followed by c followed by b followed by a ''dcba

which is dcba , which is what we wanted! 这就是dcba ,这就是我们想要的!

Wrapping your head around recursion isn't easy. 要想绕过递归并不容易。 Try to solve some other problems with it or do some exercises that require it; 尝试解决它的一些其他问题或进行一些需要它的练习; this kind of practice really helps understanding. 这种做法确实有助于理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM