在Python中遍历斯特恩-布罗科特树的部分节点

2 投票
2 回答
1464 浏览
提问于 2025-04-18 15:03

我的目标是遍历一对对的数字 [a,b],要求 a 和 b 互质,并且 a+b 小于等于 n。比如说,如果 n=8,我想遍历的对包括 [1, 2]、[2, 3]、[3, 4]、[3, 5]、[1, 3]、[2, 5]、[1, 4]、[1, 5]、[1, 6]、[1, 7]。
我最初的想法是用递归函数来实现,利用 Stern-Brocot 树:

def Stern_Brocot(n,a=0,b=1,c=1,d=1):
if(a+b+c+d>n):
    return 0
x=Stern_Brocot(n,a+c,b+d,c,d)
y=Stern_Brocot(n,a,b,a+c,b+d)
if(x==0):
    if(y==0):
        return [a+c,b+d]
    else:
        return [a+c]+[b+d]+y
else:
    if(y==0):
        return [a+c]+[b+d]+x
    else:
        return [a+c]+[b+d]+x+y

正如预期的那样,

>>> Stern_Brocot(8)
[1, 2, 2, 3, 3, 4, 3, 5, 1, 3, 2, 5, 1, 4, 1, 5, 1, 6, 1, 7]

对于 n 小于等于 995 的情况,这个方法运行得很好。但当 n 大于等于 996 时,就出现了这个错误:

Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    a=Stern_Brocot(996)
  File "C:\Users\Pim\Documents\C Programmeren en Numerieke Wisk\Python\PE\PE127.py", line 35, in Stern_Brocot
    y=Stern_Brocot(n,a,b,a+c,b+d)
...
  File "C:\Users\Pim\Documents\C Programmeren en Numerieke Wisk\Python\PE\PE127.py", line 35, in Stern_Brocot
    y=Stern_Brocot(n,a,b,a+c,b+d)
RuntimeError: maximum recursion depth exceeded in comparison

因为我想让 n 等于 120000,所以这个方法就不行了。 所以我的问题是:有没有什么好的方法可以遍历 Stern-Brocot 树的部分?(如果有其他方法可以遍历互质的整数,那也很好)。

2 个回答

0

在定义 Stern_Brocot 之前,先加上 sys.setrecursionlimit(120000)。这样做是为了把程序的递归调用限制设置为120000。

所以,你可以这样做:

import sys
sys.setrecursionlimit(120000)

def Stern_Brocot(n,a=0,b=1,c=1,d=1):
    if(a+b+c+d>n):
        return 0
    x=Stern_Brocot(n,a+c,b+d,c,d)
    y=Stern_Brocot(n,a,b,a+c,b+d)
    if(x==0):
        if(y==0):
            return [a+c,b+d]
        else:
            return [a+c]+[b+d]+y
    else:
        if(y==0):
            return [a+c]+[b+d]+x
        else:
            return [a+c]+[b+d]+x+y
2

这里有一个非递归的实现方式

def Stern_Brocot(n):
    states = [(0, 1, 1, 1)]
    result = []
    while len(states) != 0:
        a, b, c, d = states.pop()
        if a + b + c + d <= n:
            result.append((a+c, b+d))
            states.append((a, b, a+c, b+d))
            states.append((a+c, b+d, c, d))
    return result

撰写回答