python解决递归栈溢出的方法,尾递归

递归算法堆栈溢出 递归算法:     一种直接或者间接的调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的。 特点:   ①递归就是在过程或者函数里调用自身。   ②在使用递归策略时,必须有一个明确的递归条件,称为递归出口。   ③递归算法解题通常显得很简洁,但递归算法解题的效率较低。所以一般不倡导使用递归算法设计程序。   ④在递归调用的过程当中系统的每一层的返回点、局部变量 阅读详情

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

上面的fact(n)函数由于return n * fact(n - 1)引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:

def fact(n):
    return fact_iter(n, 1)
 
def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

可以看到,return fact_iter(num - 1, num * product)仅返回递归函数本身,num - 1和num * product在函数调用前就会被计算,不影响函数调用。

fact(5)对应的fact_iter(5, 1)的调用如下:

===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120

尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

小结
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

34.1:如何解决Python的递归调用问题?(课程共8100字,4个代码举例) 递归是一种重要的编程技巧,在Python中有着广泛的应用。为了避免递归调用产生的问题,我们可以采用四种方法来解决问题,并注意一些细节问题。在实际编程中,我们应该根据具体情况选择适当的方法来解决递归调用问题,保证程序的正确性和效率。同时,我们也需要不断学习和探索,提高自己的编程能力和解决问题的能力。 阅读详情

相关推荐

QMT实盘交易入门:5分钟搞定ETF全球配置策略(附完整代码)

本文详细介绍了如何使用QMT平台实现ETF全球配置策略,从环境准备到策略编写、实盘部署全流程仅需5分钟。通过xtquant库对接交易所接口,提供完整的动量轮动策略代码,帮助投资者快速掌握自动交易技术,优化全球资产配置。

weixin_30675247的博客 334

详解什么是尾递归(通俗易懂,示例讲解)

在传统的递归中,典型的模型是首先执行递归调用,然后获取递归调用的返回值并计算结果。以这种方式,在每次递归调用返回之前,您不会得到计算结果。 在尾递归中,首先执行计算,然后执行递归调用,将当前步骤的结果传递给下一个递归步骤。这导致最后一个语句采用的形式(return (recursive-function params))。基本上,任何给定递归步骤的返回值与下一个递归调用的返回值相同。 我们考虑...

Vermont_的博客 5万+

iOS WKWebView H5微信支付跳转

iOS WKWebView H5微信支付跳转 需求:iOS客户端实现嵌入H5进行微信支付跳转到微信客户端,支付完成后再跳转回我们的APP,解决WKWebView无法跳转回APP的BUG. 阅读前提: 了解WKWebView基本初始化及使用 了解如何利用URL Schemes进行应用间跳转 公司或个人已经在微信后台注册了一级域名 GitHub地址(附代码) :iOS WKWebView H5微信支付跳转 简书地址 :iOS WKWebView H5微信支付跳转 博客地址 :iOS WKWe...

ForeverMyheart的博客 2046

Python之递归和栈

递归 递归是很多算法都使用的一种编程方法,具体的表现在于自己调用自己。 每个递归函数都有两部分:基线条件 与 递归条件 递归条件:指的是函数调用自己 基线条件:指的是函数不再调用自己,从而避免形成无限循环。 代码实现递归 def count_down(i): print(i) if i<=1: return else: count_...

why404 933

Obsidian+llama3:终于搭建了自己的知识库

Obsidian 的 Smart Connections,超出了我原本的预期,于是结合新模型非常方便地搭建了我的个人知识库。

谢彦的技术博客 3712

SAP SD科目确定:从配置到凭证的财务集成核心

本文深入解析SAP SD科目确定的核心价值与配置实践,涵盖从主数据准备到财务凭证生成的全流程。通过六步配置法和KOFI00过程拆解,帮助企业实现销售与财务模块的高效集成,确保收入、成本等数据准确归集至对应会计科目,提升财务自动化水平与数据准确性。

weixin_33491377的博客 251

解决python递归栈溢出

使用python写的递归程序如果递归太深, 那么极有可能因为超过系统默认的递归深度限制而出现RuntimeError: maximum recursion depth exceeded in comparison 的错误, 解决方法很简单, 人为将系统设定的递归深度设置为一个较大的值即可:import sys sys.setrecursionlimit(1000000) #括号中的值为递归深度

lalala 5431

【小程序】支付宝直付通解决方案

支付宝直付通是支付宝为小程序提供的一种支付解决方案,可以实现小程序中直接使用支付宝进行支付。以上是一个简单的支付宝直付通解决方案及相关代码示例。具体的使用还需要根据自己的业务需求进行定制化开发和调整。

qq_31532979的贺公子之数据科学与艺术博客,致力于科技向善,拥抱开源,要用技术的影响力来领导团队,而不是威权和职位! 1281

Python栈溢出

Python 栈溢出python3.5.4 递归函数最恶心的时候莫非栈溢出(Stack overflow)。如何解决? RuntimeError: maximum recursion depth exceeded in comparison

a5186050的博客 4918

UVC协议在STM32H7上的移植实战案例

手把手带你把UVC协议移植到STM32H7平台,重点解决USB高速枚举、视频流控制与YUV数据打包等关键问题。基于HAL库实现符合UVC 1.5规范的即插即用摄像头功能,让嵌入式设备轻松变身标准UVC视频源。

weixin_42437253的博客 396

Linux故障排查和性能优化面试题及参考答案

在 Linux 系统中,负载(Load Average)是衡量系统繁忙程度的一个重要指标,它表示系统在特定时间间隔内运行队列中的平均进程数。负载值反映了系统当前的工作压力,主要包括 CPU 等待运行的进程数量和处于不可中断睡眠状态(通常是等待 I/O 操作完成)的进程数量。负载平均值通常有三个数值,分别代表过去 1 分钟、5 分钟和 15 分钟内的系统平均负载。例如,在使用uptime命令或查看文件时,会看到类似这样的输出,这三个数值依次表示过去 1 分钟、5 分钟和 15 分钟的负载平均值。

大模型大数据攻城狮的专栏 1081

【Python】递归和栈溢出

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。 比如python 默認的遞歸深度為1000, 所以如果直接執行func(1.

宁静以致远 1829

WPF数据绑定Binding对数据的转换与效验(四)

Binding的作用就是架在Source与Target之间的桥梁,数据可以在这座桥梁的帮助下来流通。就像现实世界中的桥梁会设置一些关卡进行安检一样,Binding这座桥上也可以设置关卡对数据的有效性进行检验,不仅如此,当Binding的两端要求使用不同的数据类型时,我们还可以为数据设置转换器。Binding用于数据有效性检验的关卡是它的ValidationRules属性,用于数据类型转换的关卡是它的Converter属性。

qq_30725967的博客 1626

递归函数溢出---尾递归

递归函数 使用递归函数要防止栈的溢出,函数调用是通过栈这种数据结构来实现的,没进入一个函数,就会多一层栈帧,每执行完一个函数(或者可理解为函数返回),就会减少一个栈帧。但栈不是无限大的,当递归调用太多会导致栈溢出。 解决栈溢出的方法:尾递归。 尾递归是指在函数返回时调用其本身而不是表达式。 使用尾递归,编译器和解释器会进行优化, 栈内只有一帧。 循环可看做特殊的尾递归。

passionkk的专栏 850

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Python 函数-递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。举个例子,我们来计算阶乘,用函数fact(n)表示,可以看出:fact(n)=n!所以,fact(n)可以表示为,只有n=1时需要特殊处理。于是,fact(n)上面就是一个递归函数。如果我们计算fact(5)递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。使用递归函数需要注意防止栈溢出。

分享编程知识与技巧 致力于技术交流与学习 找我合作私聊 有偿解决计算机问题 708

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

python栈溢出_Python栈溢出【新手必学】

python3.5.4递归函数最恶心的时候莫非栈溢出(Stack overflow)。PS:另外很多人在学习Python的过程中,往往因为没有好的教程或者没人指导从而导致自己容易放弃,为此我建了个Python交流.裙 :一久武其而而流一思(数字的谐音)转换下可以找到了,里面有最新Python教程项目可拿,不懂的问题多跟里面的人交流,都会解决哦!如何解决?人为设置递归深度使用python写的递归程序...

weixin_39841709的博客 193

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

python递归_Python开启尾递归优化!

Python尾递归优化一般递归与尾递归一般递归:def normal_recursion(n):if n == 1:return 1else:return n + normal_recursion(n-1)执行:normal_recursion(5)5 + normal_recursion(4)5 + 4 + normal_recursion(3)5 + 4 + 3 + normal_recurs...

weixin_39987120的博客 96

python递归求和_记一种避免Python 递归溢出的方法

Python 在默认的情况下对一个递归函数会设置一个最大递归层数(maximum recursion depth)。 当一个递归函数的递归层数大于这个值之后程序就会终止并抛出一个异常。这是python为了防止栈溢出而采取的一个防护措施。但是python默认的这个最大递归层数着实有一些保守(大概在1000左),这使得我们无法跑输入数据比较大的递归程序。对于这样的一个限制,常用的一些解决方案包括把递归...

weixin_39912984的博客 385

python静态递归函数_python递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。于是,fact(n)用递归的方式写出来就是:上面就是一个递归函数。可以试试:如果我们计算fact(5),可以根据函数定义看...

weixin_29027285的博客 157

Python递归函数

#1、计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出: #fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n def fact(n): if n==1: return 1 else: return(n * fact...

yangxy的博客 755

关于Python递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是。举个例子,我们来n!= 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。(n):n==1:1上面就是一个。可以试试:1120如果我们计算fact(5),可以根据函数定义看到计算过程如下:===> 120递归函数的优点是定义简单,逻辑清晰。

xinyuerr的博客 74

爬虫遇到栈溢出(stack overflow)的问题

今天在用python爬虫抓取网页信息的时候,出现了一个关于栈溢出的错误:Fatal Python error: Cannot recover from stack overflow.没有找到正确的解决方案,然后就搜索了跟栈溢出相关的知识并检查了代码,发现了问题所在:使用函数时递归调用次数过多(1000多),导致栈溢出。在Python中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函

qq_34178562的博客 1万+

玩转python: 几个案例理解-递归算法如何优化

几个案例理解递归算法如何进行优化

Luckstar2019的博客 1392
上一篇: 删除链表中重复的结点
下一篇: 字符串转换成一个整数
程序员椰子橙
博客等级 码龄9年 46粉丝 163原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值