用python写递归方法解决八皇后问题时,出现了很多问题
递归无法退出
递归中的return只会退出当前调用的函数 f t f_t ft,如果仅在 f t f_t ft中return了,那么程序不会直接退出整个递归调用,而是返回到上一个调用函数 f t − 1 f_{t-1} ft−1,继续执行 f t − 1 f_{t-1} ft−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),程序依然没能走完,仍然栈溢出,除了强制增加栈空间外,可以考虑回溯剪枝或者将回溯递归改写成非递归的形式。