斐波那契调用图中的值分区(调用图是二叉树)
Posted
技术标签:
【中文标题】斐波那契调用图中的值分区(调用图是二叉树)【英文标题】:Partitions of values in a fibonacci call graph (call graph is a binary tree) 【发布时间】:2012-03-27 22:34:55 【问题描述】:我有一个正在进行的项目调查斐波那契数列,这只是一个个人项目,我创建了一个二进制 tree class
,它生成了斐波那契调用图的二叉树,所以对于 f(3)
,我生成了树:
我想创建一个我的tree class
get_partitions()
的方法,它遍历树以生成root value
的分区,我在这里将顺序不同的summands 视为不同 分区;因此对于f(3)
的示例,get_partitions()
方法将遍历树并产生:
Partion 1: 2,1
Partion 2: 2,1,0
Partion 3: 1,1,1
Partion 4: 1,1,1,0
Partion 5: 1,0,1,1
Partion 6: 1,0,1,1,0
最终我想枚举分割root value
的斐波那契数的每个排列,在这种情况下为3
,所以对于Partition 1
,枚举将是(2,1),(1,2)
,或者Partion 2
将枚举(2,1,0),(2,0,1),(1,2,0),(1,0,2),(0,2,1),(0,1,2)
等等……
[Edit 1] 我担心这个例子中的 Partion 4
和 Partion 5
因为枚举这些分区的所有组合会产生 duplicate 分区。
给定root value
的组合数会产生一个加泰罗尼亚数,这是否正确?
我的Tree class
是:
class FibTree(object):
"""Class which builds binary tree from Fibonacci function call graph"""
def __init__(self, n, parent=None, level=None, i=None):
if level is None:
level = 0
if i is None:
i = 1
self.n = n
self.parent = parent
self.level = level
self.i = i # Node index value
if n < 2:
self.left = None
self.right = None
self.value = n
else:
self.left = FibTree(n - 1, self, level + 1, i*2)
self.right = FibTree(n - 2, self, level + 1, (i*2)+1)
self.value = self.left.value + self.right.value
对于生成树类方法的任何帮助以及对我的问题的数学启发,我将不胜感激。
[编辑:]我如何获得我的分区
所有分区的总和必须为 Root
值:Partion 1:
取自级别 1 (2,1)
Partion 2:
使用 left child node
的值 root
,但现在取root
节点(1,0)
的right child node
,给(2,1,0)
的一个PartionPartion 3:
由于root
节点的right child node
的遍历已经耗尽,遍历到@987654354的下一级root
的 @ 值(级别 2),并将这些子节点值用作分区 (1,1)
的第一部分,然后取 root
节点 (1) 的 right child node
值,得到 @987654359 的分区@Partion 4:
保留前一个分区(1,1)
的初始分区值,但与Partion 2
一样,取root
节点(1,0)
的right child node
的子节点的值,给出一个(1,1,1,0)
Partion 5:
的分区作为根的左孩子的左孩子,有孩子,使用这些作为分区的第一部分 (1,0)
然后取右孩子值root
(1) 的左子节点,给出到目前为止(1,0,1)
的分区,然后取根(1)
的右子节点,给出(1,0,1,1)
的最后一个分区@@987654373 @ 作为 Partion 5,取 Partion 5 的第一部分(1,0,1)
,然后作为 Partion 2 和 4,取根的右节点的子节点的值。
【问题讨论】:
问题到底是什么?你被困在哪里了? 嗨@svick,生成所有分区排列的方法的伪代码。谢谢 有什么理由让1
节点拥有1
和0
子节点?似乎递归应该在那里终止。如果没有,您可以假设您可以拥有任意多个 0
孩子,因为他们实际上并没有贡献任何东西。
嗨@templatetypedef 对递归斐波那契函数是真实的,在终止点1
节点确实有一个1
和0
孩子,但正如你所说,它可能是任意的@ 987654382@ children 最终将证明对我没有用,因为它们没有大小,所以我可能需要以某种方式将它们过滤掉。
你能分享你是如何生成你的分区的吗...伪代码或者只是英文会很好。我对您如何获得它们感到有些困惑。
【参考方案1】:
这是一个生成器,它可以产生你想要的那种值,但我没有尝试找到一个完全优化的解决方案,因为你的问题在某些地方有点令人困惑。
您确定要包含 0 吗?它不是完全任意的,因为分区中零的最大数量是一的数量(例如 [1, 0, 1, 0, 1, 0]),但它们似乎没有添加任何东西。
您究竟是如何对分区进行排序的?当 n=3 并忽略零时,它们似乎是按长度排序的,但如果 n=8,例如,是 [2, 2, 2, 2] 在 [1, 2, 2, 3] 之前还是之后?
你真的想要一个类来做这件事,还是只是因为这似乎是最简单的方法而将其用作示例?
此代码将产生斐波那契数列中所有值的排列,这些排列添加到n
,包括n
本身。只有当n
确实在序列中时它才会起作用(例如fibs(4)
会引发异常)。
代码如下:
def fibs(n, _pairs=None):
'Return partitions in the fibonacci sequence'
if _pairs is None:
# Generate a dict of fib numbers, values are the previous two numbers
# E.g. ..., 8: [3, 5], 13: [5, 8], ... n: [fib_n-2, fib_n-1]
a, b, c = 0, 1, 1
_pairs = 1: [0, 1]
while c < n:
a, b = b, a + b
c = a + b
_pairs[c] = [a, b]
# Yield every sum combination of pairs
yield (n,)
if n == 1:
yield (1, 0)
else:
right, left = _pairs[n]
for vl in fibs(left, _pairs):
for vr in fibs(right, _pairs):
yield vl + vr
您可以使用set(tuple(sorted(i)) for i in fibs(n))
轻松过滤掉重复项,并使用itertools.permutations
创建排列。
【讨论】:
谢谢@aquavitae 我会调查你的答案并回复;我看到根据遍历树的方式对分区进行排序 - 特定的顺序并不重要。我已将其设置为Class
,我也在添加它 - 我发现这是一种将事物组合在一起的好方法,此外还学习了二叉树、遍历等...我不确定我需要包括零,但要开始,因为零是递归生成 Fib 序列自然产生的。谢谢亚历克斯
上述函数fibs()
似乎不适用于n
以上3
的任何值
缺少一行,这意味着输出不完整,但它似乎对我来说适用于更大的数字。究竟是什么行不通?输出不正确吗?请注意,它仅适用于斐波那契数列中n
的值。
嗨@aquavitae 我打电话给你的fibs(n)
函数,比如:print list(fibs(4))
,它有一个Key error
;如果我用小于 4 的数字调用该方法:print list(fibs(3))
它会输出1
和0
的列表。
4 不在斐波那契数列中(请参阅我在答案中添加的注释)。尝试 5 或 8。以上是关于斐波那契调用图中的值分区(调用图是二叉树)的主要内容,如果未能解决你的问题,请参考以下文章