问题:
有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只对自递归起作用,还不能用于互递归。