Python基础夯实:递归算法

简介: 递归算法

一、函数执行流程


http://pythontutor.com/visualize.html#mode=edit

image.png

示例.png


  • 全局帧中生成 foo1foo2foo3main 函数对象
  • main 函数调用
  • main 中查找内建函数 print 压栈,将常量字符串压栈,调用函数,弹出栈顶
  • main 中全局查找函数 foo1 压栈,将常量 100、101 压栈,调用函数 foo1,创建栈帧。print 函数压栈,字符串和变量 bb1 压栈,调用函数,弹出栈顶,返回值
  • main 中全局查找函数 foo2 压栈,将常量 200 压栈,调用函数 foo2,创建栈帧。foo3 函数压栈,变量 c 引用压栈,调用 foo3,创建栈帧。foo3 完成 print 函数调用后返回。foo2 恢复调用,执行 print 后,返回值。mainfoo2 调用结束弹出栈顶。main 继续执行 print 函数调用,弹出栈顶。main 函数返回

image.png

示例.png

image.png

示例.png


二、递归 Recursion


  • 函数直接或见着调用自身就是 递归
  • 递归需要有边界条件、递归前进段、递归返回段
  • 递归一定要有 边界条件
  • 当边界条件不满足的时候,递归前进
  • 当边界条件满足的时候,递归返回

    image.png
    示例.png

2.1 斐波那契数列 Fibonacci number:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ....


  • F(n) 为该数列第 n 项(n∈N*),那么这句话可写成:F(n)=F(n-1)+F(n-2)
  • F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)

a = 0
b = 1
n = 10   # 55
# 循环实现
for i in range(n -1):
    a, b = b, a + b
else:
    print(b)
# 递归实现
def fib(n):
    return 1 if n < 3 else fib(n-1) + fib(n-2)
  • fib(5) 解析
    fib(4) + fib(3)
    fib(4) 调用 fib(3)fib(2)
    fib(3) 调用 fib(2)fib(1)
    fib(2)fib(1) 是边界 return 1,所有函数调用逐层返回


2.2 递归要求


  • 递归一定要有退出条件,递归调用一定要执行到这个退出条件。没有退出条件的递归调用,就是无限调用
  • 递归调用的深度不宜过深
  • Python 对递归调用的深度做了限制,以保护解释器
  • 超过递归深度限制,抛出 RecursionError: maxinum recursion depth exceeded 超出最大深度
  • sys.getrecursionlimit()


2.3 递归性能 fib(35) 比较


  • for 循环

    image.png
    示例.png
  • 递归
    image.png

    示例.png


2.4 递归的性能


  • 循环稍微复杂一些,但是只要不是死循环,可多次迭代直至算出结果
  • fib 函数代码极简易懂,但是只能获取到最外层函数调用,内部递归结果都是中间结果。而且给定一个 n 都要进行近 2n 次递归,深度越深,效率越低。为了获取斐波那契数列需要外面再套一个 n 次循环,效率就更低了
  • 递归还有深度限制,若递归复杂,函数反复压栈,栈内存很快就溢出了
  • 斐波那契数列改进

def fib(n, a=0, b=1):
    a, b = b, a+b
    if n == 1:
        return a
    return fib(n-1, a, b)
print(fib(4))
  • 改进后的函数和循环的思想类似
  • 参数 n 是边界条件,用 n 来计数
  • 上次的计算结果直接作为函数的实参
  • 效率高
  • 和循环比较,性能相近。所以并不是说递归一定效率低下,但递归有深度限制


2.5 间接递归

def foo1():
    foo2()
def foo2():
    foo1()
foo1()

间接递归,是通过别的函数调用了函数自身

拖构成了循环递归调用是非常危险的,但往往这种情况在代码复杂情况下,很可能发生这种调用,要用代码的规范来避免递归调用的发生


三、递归总结


  • 递归是一种很自然的表达,符合逻辑思维
  • 递归相对运行效率低,每一次调用函数都要开辟栈帧
  • 递归有深度限制,若递归层次太深,函数反复压栈,栈内存很快就溢出了
  • 若是有限次数的递归,可使用递归调用,或使用循环代替,循环代码稍复杂一些,但只要不是死循环,可多次迭代直至算出结果
  • 绝大多数递归,都可使用循环实现
  • 即使递归代码很简洁,但 能不用则不用 递归


四、递归练习


4.1 求 n 的阶乘


  • 按公式

def fac(n):
    if n == 1:
        return 1
    return n * fac(n-1)
def fac(n):
    return 1 if n < 2 else n * fac(n-1)
  • 按循环

n = 6
fac = 1
for i in range(n, 0, -1):   # 计数器 n 次
    fac = fac * i
print(fac)
def fac1(n, fac=1):
    fac = fac * n
    if n == 1:
        return fac
    return fac1(n-1, fac)


4.2 将一个数逆序放入列表中,例如 1234 => [4, 3, 2, 1]


  • 传入字符串

target = []
def revert(data):
    target.append(data[-1])
    if len(data) == 1:
        return target
    return revert(data[:-1])
revert('1234')
def revert(data, target=None):
    if target is None:
        target = list()
    target.append(data[-1])
    if len(data) == 1:
        return target
    return revert(data[:-1], target)
revert('1234')
def revert(data):
    if data == '':
        return []
    return [data[-1]] + revert(data[:-1])
revert('1234')
  • 传入数字

def revert(data, target=None):
    if target is None:
        target = list()
    if not isinstance(target, list):
        return
    x, y = divmod(data, 10)
    target.append(y)
    if x:
        return revert(x, target)
    return target
revert(120340)


4.3 解决猴子吃桃问题


  • 按题意

def peach(days=1):
    if days == 10:
        return 1
    return 2 * (peach(days+1) +1)
def peach(days=10):
    if days == 1:
        return 1
    return 2 * (peach(days-1) + 1)
  • 按循环

peach = 1
for i in range(9):
    peach = 2 * (peach + 1)
print(peach)
def fn(days=9, peach=1):
    peach = 2 * (peach + 1)
    if days == 1:
        return peach
    return fn(days-1, peach)
fn()
目录
相关文章
|
12天前
|
数据采集 机器学习/深度学习 数据可视化
【优秀python web系统毕设】基于python的全国招聘数据分析可视化系统,包括随机森林算法
本文介绍了一个基于Python的全国招聘数据分析可视化系统,该系统利用数据挖掘技术、随机森林算法和数据可视化技术,从招聘网站抓取数据,进行处理、分析和预测,帮助用户洞察招聘市场,为求职者和企业提供决策支持。
|
12天前
|
搜索推荐 前端开发 数据可视化
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
|
13天前
|
数据采集 算法 数据可视化
基于Python的k-means聚类分析算法的实现与应用,可以用在电商评论、招聘信息等各个领域的文本聚类及指标聚类,效果很好
本文介绍了基于Python实现的k-means聚类分析算法,并通过微博考研话题的数据清洗、聚类数量评估、聚类分析实现与结果可视化等步骤,展示了该算法在文本聚类领域的应用效果。
|
12天前
|
机器学习/深度学习 数据采集 算法
【优秀python算法毕设】基于python时间序列模型分析气温变化趋势的设计与实现
本文介绍了一个基于Python的时间序列模型,用于分析和预测2021-2022年重庆地区的气温变化趋势,通过ARIMA和LSTM模型的应用,揭示了气温的季节性和趋势性变化,并提供了对未来气温变化的预测,有助于气象预报和相关决策制定。
【优秀python算法毕设】基于python时间序列模型分析气温变化趋势的设计与实现
|
7天前
|
编解码 算法 Linux
Linux平台下RTSP|RTMP播放器如何跟python交互投递RGB数据供视觉算法分析
在对接Linux平台的RTSP播放模块时,需将播放数据同时提供给Python进行视觉算法分析。技术实现上,可在播放时通过回调函数获取视频帧数据,并以RGB32格式输出。利用`SetVideoFrameCallBackV2`接口设定缩放后的视频帧回调,以满足算法所需的分辨率。回调函数中,每收到一帧数据即保存为bitmap文件。Python端只需读取指定文件夹中的bitmap文件,即可进行视频数据的分析处理。此方案简单有效,但应注意控制输出的bitmap文件数量以避免内存占用过高。
|
8天前
|
JSON 算法 API
京东以图搜图功能API接口调用算法源码python
京东图搜接口是一款强大工具,通过上传图片即可搜索京东平台上的商品。适合电商平台、比价应用及需商品识别服务的场景。使用前需了解接口功能并注册开发者账号获取Key和Secret;准备好图片的Base64编码和AppKey;生成安全签名后,利用HTTP客户端发送POST请求至接口URL;最后解析JSON响应数据以获取商品信息。
|
7天前
|
算法 Python
python多继承的3C算法是什么?怎么用?
有很多地方都说python多继承的继承顺序,是按照深度遍历的方式,其实python多继承顺序的算法,不是严格意义上的深度遍历,而是基于深度遍历基础上优化出一种叫3C算法
|
8天前
|
数据采集 机器学习/深度学习 算法
【python】python客户信息审计风险决策树算法分类预测(源码+数据集+论文)【独一无二】
【python】python客户信息审计风险决策树算法分类预测(源码+数据集+论文)【独一无二】
|
12天前
|
机器学习/深度学习 数据采集 数据可视化
【优秀python系统毕设】基于Python flask的气象数据可视化系统设计与实现,有LSTM算法预测气温
本文介绍了一个基于Python Flask框架开发的气象数据可视化系统,该系统集成了数据获取、处理、存储、LSTM算法气温预测以及多种数据可视化功能,旨在提高气象数据的利用价值并推动气象领域的发展。
|
12天前
|
数据可视化 算法 前端开发
基于python flask+pyecharts实现的中药数据可视化大屏,实现基于Apriori算法的药品功效关系的关联规则
本文介绍了一个基于Python Flask和Pyecharts实现的中药数据可视化大屏,该系统应用Apriori算法挖掘中药药材与功效之间的关联规则,为中医药学研究提供了数据支持和可视化分析工具。