信春哥!Python递归原地满状态变显式堆栈!入教即送尾递归优化!

问题:

有Python函数一枚,用递归写成。运行时超出Python的递归深度,现欲将其由在堆栈中分配空间改为在堆中分配空间(即用malloc)。

解决方法:

首先,from heaprecursion import *。然后对目标函数进行改造,假设要改造的递归函数为def func(p1, p2):

1.把函数中的递归调用func(exp1,exp2)改成yield RECURSION(exp1,exp2),即把所有"func"替换成"yield RECURSION"。

2.把函数中所有的"return"替换成yield。如果是尾递归return func(exp1, exp2)则改成yield TAIL(exp1, exp2)。

最后这样调用改造好的函数:heaprun(f, exp1, exp2)

例子:
from  heaprecursion  import   *

def  sumlist(l):
    
if  len(l) == 0:  return  0
    x
= l.pop()
    y
= sumlist(l)
    
return  x + y

改造成这样:    
def  sumlist2(l):
    
if  len(l) == 0:  yield  0
    x
= l.pop()
    y
= yield  RECURSION (l)
    
yield  x + y; 
调用:
heaprun(sumlist2, range(
10000 ))
    
def  factorial(n, accu):
    
if  n == 0:
        
return   1
    
else :
        
return  factorial(n - 1 , accu * n)
改造成这样:
def  factorial2(n, accu):
    
if  n == 0:
        
yield  accu
    
else :
        
yield  TAIL(n - 1 , accu * n)
调用:
heaprun(factorial2, 
10000 1 )

t
= ( 1 ,
   (
2 ,
    
4 ,
    (
5 ,
     
6 ,
     
7 )),
   (
3 ,
    
8 ,
    
9 ))

def  inorder(t):
    
if  type(t)  is  int:
        
print  t
    
else :
        inorder(t[
1 ])
        
print  t[0]
        inorder(t[
2 ])
改造成这样:
def  inorder2(t):
    
if  type(t)  is  int:
        
print  t
    
else :
        
yield  RECURSION(t[ 1 ])
        
print  t[0]
        
yield  TAIL(t[ 2 ])
调用:
heaprun(inorder2, t)


heaprecursion.py代码如下:
def  forward(it, arg):
    
#  move iterator 'it' by calling 'next'(when 'arg' is None) or 'send'
     #  return what 'next' or 'send' returns, or None if 'it' is at its end
     try :
        
if  arg == None:
            
return  it.next()
        
else :
            
return  it.send(arg)
    
except  StopIteration:  pass
    
return  None

        
class  RECURSION(object):
    
def   __init__ (self,  * args):
        self.args
= args
    
class  TAIL(RECURSION):
    
pass

def  heaprun(f,  * args):
    stack
= [f( * args)]
    param
= None
    
while ( 1 ):
        v
= forward(stack[ - 1 ], param)
        
if  isinstance(v, RECURSION):
            
if  type(v) == TAIL:
                stack.pop()
            stack.append(f(
* (v.args)))
            param
= None
        
else :
            stack.pop()
            
if  stack:
                param
= v
            
else :
                
return  v
 限制:

目前heaprecursion.py只对自递归起作用,还不能用于互递归。

你可能感兴趣的:(python)