递归

柔情痞子 提交于 2019-11-28 15:31:50

一、什么是函数递归

函数的嵌套调用是:函数嵌套函数。函数的递归调用:它是一种特殊的嵌套调用,但是它在调用一个函数的过程中,又直接或间接地调用了它自身。

def foo():      print('from foo')      foo()    foo()  # 进入死循环

如果递归函数不断地调用函数自身,那么这个递归函数将会进入一个死循环,因此我们应该给递归函数一个明确的结束条件。

1.1 直接调用


直接调用指的是:直接在函数内部调用函数自身。

import sys    print(f"最大递归层数: {sys.getrecursionlimit()}")
最大递归层数: 3000
import sys    # 修改递归层数  sys.setrecursionlimit(10000)  def foo(n):      print('from foo',n)      foo(n+1)  foo(0)

1.2 间接调用


间接调用指的是:不在原函数体内调用函数自身,而是通过其他的方法间接调用函数自身。

def bar():      print('from bar')      foo()        def foo():      print('from foo')      bar()        bar()

递归必须要有两个明确的阶段:

  1. 递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小
  2. 回溯:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯。

递归的精髓在于通过不断地重复逼近一个最终的结果。

'''  ...  age(5) = age(4) + 2  age(4) = age(3) + 2  age(3) = age(2) + 2  age(2) = age(1) + 2  age(1) = 26      age(n) = age(n-1) +2   age(1) = 26  # n=1  '''      def age(n):      if n == 1:          return 26      res = age(n-1) + 2      return res      print(f"age(5): {age(5)}")
age(5): 34

二、为什么要用递归


递归的本质就是干重复的活,但是仅仅是普通的重复,我们使用while循环就可以了。」

lis = [1, [2, [3, [4, [5, [6, ]]]]]]      def tell(lis):      for i in lis:          if type(i) is list:              tell(i)          else:              print(i)      # print(f"tell(lis): {tell(lis)}")  tell(lis)
1  2  3  4  5  6

三、如何用递归?


3.1 二分法的应用


有一个从小到大排列的整型数字列表,我们判断某一个数字是不是在这个列表里面。

动图二分法查找数字23:

动图二分法查找数字1:

nums = [1, 3, 7, 11, 22, 34, 55, 78, 111, 115]    for item in nums:      if item == 10:          print('find it')          break  else:      print('not exists')
not exists

对于上述的列表我们可能可以通过一个for循环实现我们需要的功能,但是当我们的列表中的元素个数非常多时,我们还用这种方法,那是极其复杂的,因此我们可以考虑使用二分法的思想实现。

from random import randint  nums = [randint(1, 100) for i in range(100)]  nums = sorted(nums)  print(nums)
[1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91, 91, 91, 94, 99, 99, 100]
def search(search_num, nums):      mid_index = len(nums)//2      print(nums)      if not nums:          print('not exists')          return      if search_num > nums[mid_index]:          # in the right          nums = nums[mid_index+1:]          search(search_num, nums)      elif search_num < nums[mid_index]:          # in the left          nums = nums[:mid_index]          search(search_num, nums)      else:          print('find it')      search(7, nums)
[1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91, 91, 91, 94, 99, 99, 100]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7]  [6, 6, 7, 7, 7]  find it

 

一、什么是函数递归

函数的嵌套调用是:函数嵌套函数。函数的递归调用:它是一种特殊的嵌套调用,但是它在调用一个函数的过程中,又直接或间接地调用了它自身。

def foo():      print('from foo')      foo()    foo()  # 进入死循环

如果递归函数不断地调用函数自身,那么这个递归函数将会进入一个死循环,因此我们应该给递归函数一个明确的结束条件。

1.1 直接调用


直接调用指的是:直接在函数内部调用函数自身。

import sys    print(f"最大递归层数: {sys.getrecursionlimit()}")
最大递归层数: 3000
import sys    # 修改递归层数  sys.setrecursionlimit(10000)  def foo(n):      print('from foo',n)      foo(n+1)  foo(0)

1.2 间接调用


间接调用指的是:不在原函数体内调用函数自身,而是通过其他的方法间接调用函数自身。

def bar():      print('from bar')      foo()        def foo():      print('from foo')      bar()        bar()

递归必须要有两个明确的阶段:

  1. 递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小
  2. 回溯:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯。

递归的精髓在于通过不断地重复逼近一个最终的结果。

'''  ...  age(5) = age(4) + 2  age(4) = age(3) + 2  age(3) = age(2) + 2  age(2) = age(1) + 2  age(1) = 26      age(n) = age(n-1) +2   age(1) = 26  # n=1  '''      def age(n):      if n == 1:          return 26      res = age(n-1) + 2      return res      print(f"age(5): {age(5)}")
age(5): 34

二、为什么要用递归


递归的本质就是干重复的活,但是仅仅是普通的重复,我们使用while循环就可以了。」

lis = [1, [2, [3, [4, [5, [6, ]]]]]]      def tell(lis):      for i in lis:          if type(i) is list:              tell(i)          else:              print(i)      # print(f"tell(lis): {tell(lis)}")  tell(lis)
1  2  3  4  5  6

三、如何用递归?


3.1 二分法的应用


有一个从小到大排列的整型数字列表,我们判断某一个数字是不是在这个列表里面。

动图二分法查找数字23:

动图二分法查找数字1:

nums = [1, 3, 7, 11, 22, 34, 55, 78, 111, 115]    for item in nums:      if item == 10:          print('find it')          break  else:      print('not exists')
not exists

对于上述的列表我们可能可以通过一个for循环实现我们需要的功能,但是当我们的列表中的元素个数非常多时,我们还用这种方法,那是极其复杂的,因此我们可以考虑使用二分法的思想实现。

from random import randint  nums = [randint(1, 100) for i in range(100)]  nums = sorted(nums)  print(nums)
[1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91, 91, 91, 94, 99, 99, 100]
def search(search_num, nums):      mid_index = len(nums)//2      print(nums)      if not nums:          print('not exists')          return      if search_num > nums[mid_index]:          # in the right          nums = nums[mid_index+1:]          search(search_num, nums)      elif search_num < nums[mid_index]:          # in the left          nums = nums[:mid_index]          search(search_num, nums)      else:          print('find it')      search(7, nums)
[1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91, 91, 91, 94, 99, 99, 100]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21]  [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7]  [6, 6, 7, 7, 7]  find it

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!