递归的定义——在一个函数里再调用这个函数本身
现在我们已经大概知道刚刚讲的story函数做了什么,就是在一个函数里再调用这个函数本身,这种魔性的使用函数的方式就叫做递归。
刚刚我们就已经写了一个最简单的递归函数。
递归的最大深度——997
正如你们刚刚看到的,递归函数如果不受到外力的阻止会一直执行下去。但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属于它自己的名称空间,如果一直调用下去,就会造成名称空间占用太多内存的问题,于是python为了杜绝此类现象,强制的将递归层数控制在了997
可以用一段代码来验证默认递归深度:
1 def foo(n): 2 print(n) 3 n += 1 4 foo(n) 5 foo(1)
可以通过一定方法来修改默认递归深度:
1 import sys 2 print(sys.setrecursionlimit(100000))
递归实力实例讲解:
现在你们问我,alex老师多大了?我说我不告诉你,但alex比 egon 大两岁。
你想知道alex多大,你是不是还得去问egon?egon说,我也不告诉你,但我比武sir大两岁。
你又问武sir,武sir也不告诉你,他说他比金鑫大两岁。
那你问金鑫,金鑫告诉你,他40了。。。
这个时候你是不是就知道了?alex多大?
1 金鑫 40
2 武sir 42
3 egon 44
4 alex 46
以上的过程已经非常接近递归的思想,再具体的分析一下这几个人之间的规律。
使用代码表示就是:
1 age(4) = age(3) + 2 2 age(3) = age(2) + 2 3 age(2) = age(1) + 2 4 age(1) = 40
相应的,函数应该这样写:
1 def age(n): 2 if n == 1: 3 return 40 4 else: 5 return age(n-1)+2 6 7 print(age(4))
由此可以得到递归和递归函数的本质:通过两级之间的关系不断往已知条件查找(未知联系已知)使用已知条件来解决未解的问题。
递归的实际应用:算法(二分法查找)
对一串简单的,按照大小排序的数,要找到其中一个数的位置,应该怎么做?
按照常规的方法,使用index(要查找对象)就可以解决。
但是对于一个有几百万个有序排列的数的列表,使用起来就会非常慢以至于不能计算出结果。
所以我们要找一个方法来解决这样一个问题------二分法(基于递归函数)
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
我们每次都取中间的数,根据中间的数的大小来决定我们要找的数的位置(左边or右边)
这样每次不断取,就可以不断接近要取的数的位置了,最后就可以找到我们要找的数的位置了。
这就是二分查找算法!
那么落实到代码上我们应该怎么实现呢?
简单版本:
1 l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88] 2 3 def func(l,aim): 4 mid = (len(l)-1)//2 5 if l: 6 if aim > l[mid]: 7 func(l[mid+1:],aim) 8 elif aim < l[mid]: 9 func(l[:mid],aim) 10 elif aim == l[mid]: 11 print("bingo",mid) 12 else: 13 print('找不到') 14 func(l,66) 15 func(l,6)
高端版本:
1 def search(num,l,start=None,end=None): 2 start = start if start else 0 3 end = end if end else len(l) - 1 4 mid = (end - start)//2 + start 5 if start > end: 6 return None 7 elif l[mid] > num : 8 return search(num,l,start,mid-1) 9 elif l[mid] < num: 10 return search(num,l,mid+1,end) 11 elif l[mid] == num: 12 return mid