斐波那契调用图中的值分区(调用图是二叉树)

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 classget_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 4Partion 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 节点拥有10 子节点?似乎递归应该在那里终止。如果没有,您可以假设您可以拥有任意多个 0 孩子,因为他们实际上并没有贡献任何东西。 嗨@templatetypedef 对递归斐波那契函数是真实的,在终止点1 节点确实有一个10 孩子,但正如你所说,它可能是任意的@ 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)) 它会输出10 的列表。 4 不在斐波那契数列中(请参阅我在答案中添加的注释)。尝试 5 或 8。

以上是关于斐波那契调用图中的值分区(调用图是二叉树)的主要内容,如果未能解决你的问题,请参考以下文章

斐波那契数列

递归求斐波那契数列

c语言编写计算斐波那契(Fibonacci)

java用递归编程求斐波那契数列第n项

递归优化的斐波那契数列

用递归和非递归方法求解斐波那契数列