python在递归中的坑

用python写递归方法解决八皇后问题时,出现了很多问题

递归无法退出

递归中的return只会退出当前调用的函数 f t f_t ,如果仅在 f t f_t 中return了,那么程序不会直接退出整个递归调用,而是返回到上一个调用函数 f t 1 f_{t-1} ,继续执行 f t 1 f_{t-1} 中没有执行完的部分,所以在写return的时候,一定要考虑清楚return 的值和return的情况,特别是if,else比较多的情况时,经常会有一些情况忘记添加return, 为自己的函数添加return 是个好的习惯,即使并不需要确切的返回值。

RecursionError: maximum recursion depth exceeded in comparison

使用下面的命令可以获取当前递归的最大深度限制:

import sys
sys.getrecursionlimit()

我的计算机默认最大的递归深度是1000。
我们可以通过手动设置深度值:

import sys
sys.setrecursionlimit(2000000000)

但是手动设置的这个值并不是实际可以调用的函数深度,看下面的代码:

"""
i = 998 时,正常
i = 999 时,报错:maximum recursion depth exceeded in comparison
由此可知Python递归默认深度为 998

如果超过998,则最大递归深度至少+2

"""
import sys
def fact(n):
    if n==1:
        return 1
    return n + fact(n - 1)

i = 999
sys.setrecursionlimit(i+2) #设置最大递归深度,如果注释该行代码则执行报错
s = fact(i)
print("\r\n1-%s的整数之和是:%s" % (i,s))

在默认最大深度为1000的情况下,只可以调用998次函数,其实是因为,手动设置的这个数其实是栈的最大深度,在调用执行前,栈中已有其他的东西,调用inpect.stack()查看栈中的东西:
StackoverFlow:Max recursion is not exactly what sys.getrecursionlimit() claims. How come?中有更详细的解释。

但是这个值依然是有限的,最大值为2147483647,否则会报OverflowError: Python int too large to convert to C long,可以参考如下C long的取值范围:

类型名称 字节数 取值范围
signed char 1 -128~+127
short int 2 -32768~+32767
int 4 -2147483648~+2147483647
long int 4 -2147483648~+2141483647
long long long int 8 -9223372036854775808~+9223372036854775807

Process finished with exit code -1073741571 (0xC00000FD)

手动设置最大深度后,对于N=8的皇后问题,虽然能够输出部分解,且不报超过最大深度的错误,但是会报:Process finished with exit code -1073741571 (0xC00000FD),程序依然没能走完,仍然栈溢出,除了强制增加栈空间外,可以考虑回溯剪枝或者将回溯递归改写成非递归的形式。

参考文献:

  1. Python3默认递归最大深度是998

猜你喜欢

转载自blog.csdn.net/weixin_42933718/article/details/88815046