二叉树的排列

时间:2009-03-16 18:18:23

标签: algorithm language-agnostic binary-tree

考虑二叉树:

  1. n 是一个节点,如果 n 是一个整数
  2. (+ a b )是一个节点,如果 a b 是节点。
  3. 我们有以下三个操作:

    1. (+ a b ) - > (+ b a
    2. (+(+ a b c ) - > (+ a (+ b c ))
    3. (+ a (+ b c )) - > (+(+ a b c - (2.反过来)
    4. 我需要一种算法,使用这些操作给出给定树的所有可能的排列。任何操作都可以应用于任何子树。对于排列,我的意思是任何具有完全相同的叶子集的树。这可能不是很困难,但我似乎无法弄明白。

      [编辑]叶子也可以是名称(即变量),因此不能选择依赖于它们的属性作为整数。树确实代表了总和。

      [Edit2]这个练习的目的是通过查找 A -A 形式的术语来减少总和,调整树以使它们成为子树(+ A -A )以消除它们。上面的三个操作是我系统中的公理,它们需要一直使用,否则无法证明简化树等于原始树。由于我使用的是Twelf逻辑编程语言,如果我能找出算法来做我最初提出的问题,其余的就很容易了,但其他解决方案当然是受欢迎的。

6 个答案:

答案 0 :(得分:2)

似乎最简单的解决方案是对树进行深度优先遍历,将所有节点收集到列表中,生成列表的所有排列,将每个排列转储到二叉树中。

所以,给定列表(+ a(+ b c)),我们有节点[a; b; c],具有以下排列:

[a; b; c]
[a; c; b]
[b; a; c]
[b; c; a]
[c; a; b]
[c; b; a]

列表中的第一项是您的头,以下两项是子节点,接下来的四项是子子节点,依此类推。

如果您需要生成所有可能树的列表,而不仅仅是平衡树,则此increases dramatically的复杂性。在这种情况下,您需要将它们分组:

[a; b; c; d]
[(a; b); c; d]
[(a; b; c); d]
[a; (b; c); d]
[a; (b; c; d)]
[a; b; (c; d)]
[a; b; d; c]
// first permutation
[(a; b); d; c]
[(a; b; d); c]
...

每个n元组是一组节点。对于多个节点,宇宙将在算法完成之前经历热死亡。

答案 1 :(得分:1)

这个问题的解决方案无疑将包含Catalan numbers C n -1 可能存在 n 叶子的二叉树,并且有 n !可能的叶子排序,所以有 n ! * C n -1 可能的树。但是,枚举它们会稍微复杂一些。

答案 2 :(得分:1)

这些操作类似于具有以下属性的添加:闭包,关联性,交换性。对于匹配节点,每个叶子都保持相同的叶子集合,并且可以以递归方式应用。计算给定节点x的排列(在Haskell和F#的一些奇怪混合中)

let count x = match x with
  | LeafNode -> 1
  | TreeNode (a,b) -> 2 * count a * count b

答案 3 :(得分:1)

你有结社性和交换性,所以你可以自由地移动元素。 解决此问题的实用方法如下:

  • 将树梳到一边,就会得到一个清单。

  • 对列表进行排序,以便应取消的元素彼此相邻。

  • 将元素移动到子树中并取消。

要获得所需的证明,您必须为这些操作构建小样本,然后将其组合起来。

或者你可以查找AC匹配。

按照你的建议尝试所有排列只会让你发生一次大的组合爆炸。

答案 4 :(得分:1)

正如所指出的,如果你真的有交换性和相关性公理,那么最好只收集加数并将它们作为一组或一个列表处理。

如果这不令人满意,接下来要注意的是,实际上你似乎并不需要所有排列,但你想重写你的表达式以简化它们。这可以比制作所有排列更有效!

然而,要重复:),如果你只有交换性和关联性,请处理集合中的术语。

答案 5 :(得分:0)

我发现了解决树木减少的根本问题的解决方案:

  1. 从树上找到一对叶子A和-A。
  2. a)如果A和-A属于同一个孩子,请递归。
  3. b)'泡'A和-A到各自孩子的顶部。有八种可能的结果案例,但它们都看起来像这样(+(x A)( - A y))。从那里到(+(+ x y)(+ A -A))很容易。
  4. 正如所建议的那样,另一种方法是首先将树转换为列表:(+ A(+ B(+ ...))X),然后找到匹配的对A和-A并将它们带入到达顶点。我怀疑这可能会产生比上述算法更长的证据(这是不可取的),尽管我还没有尝试过。

    尽管如此,我发现原始问题引人入胜,我想尝试一下基于此的算法如何与上述算法进行比较。