版权声明:本文为博主原创文章,转载请注明作者和出处。https://blog.csdn.net/xq920831/article/details/83343144
最近都在看数学部分和机器学习视频,不太好记笔记。
今天程序员日,写点东西,关于知识点递归。
递归几个特点:
- 必须有一个明确的结束条件,要不就会变成死循环了,最终撑爆系统
- 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 递归执行效率不高,递归层次过多会导致栈溢出
# -*- coding:utf-8 -*-
# Author: Agent Xu
def Clac(n):
print(n)
if int(n/2)>0:
Clac(int(n/2))
else:
print('----')
print(n)
Clac(10)
print('==================================')
#阶乘
def Jc(n):
if (n-1)==0:
return 1
return n*Jc(n-1)
print(Jc(4))
print('==================================')
#二分查找
def Ef(m,n,k,num):
global num1
if int(abs(m-n)/2)<k:
num+=1
Ef(int(abs(m-n)/2),max(m,n),k,num)
elif int(abs(m-n)/2)>k:
num+=1
Ef(min(m,n),int(abs(m-n)/2),k,num)
else:
num1=num+1
return num1
print(Ef(0,10,1,0))
补充一个知识点:
尾递归
在讲特性时,我们说递归效率不高,因为每递归一次,就多了一层栈,递归次数太多还会导致栈溢出,这也是为什么python会默认限制递归次数的原因。但有一种方式是可以实现递归过程中不产生多层栈的,即尾递归,
如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。编译器可以做到这点,因为递归调用是当前活跃期内最后一条待执行的语句,于是当这个调用返回时栈帧中并没有其他事情可做,因此也就没有保存栈帧的必要了。通过覆盖当前的栈帧而不是在其之上重新添加一个,这样所使用的栈空间就大大缩减了,这使得实际的运行效率会变得更高。
尾递归例子
1 2 3 4 |
|
我们之前求的阶乘是尾递归么?
1 2 3 4 5 6 7 8 9 |
|
上面的这种递归计算最终的return操作是乘法操作。所以不是尾递归。因为每个活跃期的返回值都依赖于用n乘以下一个活跃期的返回值,因此每次调用产生的栈帧将不得不保存在栈上直到下一个子调用的返回值确定。