首页 > 编程知识 正文

单向递归和尾递归迭代,递归与非递归区别

时间:2023-05-05 02:42:14 阅读:153369 作者:1396

一般递归

defnormal_recursion(n ) : IFN==1: return1else : return normal _ recursion (n-1 )运行:

正常_记录(5) 5正常_记录(4) 54正常_记录(3) 54正常_记录(2) 542正常_记录

随着递归深度的增加,创建的堆栈越来越多,导致爆炸堆栈:boom:

尾递归

尾递归基于函数的尾调用每个级别的调用都直接返回函数的返回值以更新调用栈,而不创建新的调用栈。 像迭代实现一样,在时间和空间上都优化一般递归!

运行deftail_recursion(n,total=0) : IFN==0: returntotalelse 3360 return tail _ recursion (n-1,total ) :

tail_recursion(5(5(5(5(5) tail_recursion ) 4,5 ) tail_recursion ) 3,9 ) tail _ recursion (2,12 ) ttttaid

深入理解尾递归诶,所以呢? 还觉得不够吗. 谁说不需要通过尾部递归调用建立新的堆栈呢?

还是去底层看看吧

inttail_recursion(intn,int total ) if ) n==0) { return total; }else{returntail_recursion(n-1,total n ); }intmain(void ) { int total=0,n=4; tail_recursion(n,total; 返回0; } 反汇编

$ gcc-stail _ recursion.c-o normal _ recursion.s

$ gcc-s-O2 tail _ recursion.c-o tail _ recursion.sgcc打开尾部递归优化

反汇编代码如下(ATT语法) ) )。

请注意,在打开尾部递归优化之前,已经使用call调用函数创建了新的调用堆栈(LBB0_3)。

如果打开尾部递归优化,则不会生成新的调用栈,而是直接pop

返回bp指定的_tail_recursion函数的地址(pushq %rbp ),

使用的是同一个调用堆栈!

存在的问题尾部递归优化很好,但python不支持尾部递归,如果递归深度超过1000,则会报告错误

实现运行时错误3360 maximumrecursiondepthexceeded http://www.Sina.com/tail _ call _ optimized装饰件

#!/usr/ZL DBM/env python 2.4 # thisprogramshowsoffapythondecorator (# whichimplementstailcalloptimization.it # doesthisthisbython it'sowngrandparent,andcatchingsuch # exceptionstorecallthestack.importsysclasstailrecurseexception 3360 def _ _ init _ init kwargs ) : self.args=args self.kwargs=kwargsdeftail _ call _ optimized (g ) ) ) ) )。 3360 ' ' thisfunctiondecoratesafunctionwithtailcalloptimization.itdoesthisbythrowinganexceptionifitit ' sown grandparent andcarent ailcalloptimization.thisfunctionfailsifthedecoratedfunctionrecursesinanon-tail context.func (args,**kwargs ) : f 函数的默认一级递归是父调用,#尾部递归不希望生成新的函数调用)或:lcdwg调用(后面有动态图分析)的IFF.f _ backandf.f _ back.f _ back.f _ bag 抛出异常RRR的kkwargs (else : while 1: try : returng ) args,**kwargs ) except TailRecurseException、 e: #捕获异常、参数获取、 结束限定函数的递归调用堆栈args=e.args kwargs=e.kwargs func._ _ doc _ _ g._ _ doc _ _ return func @ tail _ call 来自urnACCreturnfactorial(n-1,n*acc )打印factorial ) 10000 )

打开尾部递归优化前的调用堆栈

打开尾部递归优化后(tail_call_optimized装饰器)的调用堆栈

通过pudb右栏的堆栈,可以清楚地看到调用堆栈的变化。

Python也不报告runtime error : maximumrecursiondepthexceeded错误,因为尾部递归没有调用栈嵌套。

下面介绍sys._getframe ()函数:

sys._getframe([Depth] ) : returnaframeobjectfromthecallstack.ifoptionalintegerdepthisgiven, returntheframeobjectthatmanycallsbelowthetopofthestack.ifthatisdeeperthanthecallstack,valueefrorisraised.thedefaulttforded returningtheframeatthetopofthecallstack .也就是说, 这是返回深度调用的堆栈帧对象. importsysdefget _ cur _ info (3360 printsys._ get frame )。当前文件名print sys._getframe

来自: https://segment fault.com/a/119000007641519

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。