创建大小为n的所有Bool二叉树

时间:2016-03-12 15:16:33

标签: haskell functional-programming binary-tree

我正在尝试创建大小为n的所有二叉树,但是无法想出一种方法。

树的定义如下

> data Tree :: * -> * where
>     Tip :: a -> Tree a
>     Bin :: Tree a -> Tree a -> Tree a  
>     deriving (Eq,Show)

树的大小是它拥有的提示和分档的数量。

我需要创建一个获取Int n的函数,并返回该大小的所有树的列表。

> getTrees :: Int -> [Tree Bool]

例如,对于getTrees 1,我应该获取[Tip True, Tip False],因为这是所有可能的大小为1的树。

我无法想出一种生成所有大小为n的树的方法。

2 个答案:

答案 0 :(得分:4)

首先让我们从简单的开始:大小为1的树:

> getTrees :: Int -> [Tree Bool]
> genTrees 1 = [Tip True, Tip False]

现在,我们必须考虑更多Int s。那么2呢?事实证明,如果BinTip都增加了大小,则不存在任何大小为2的树。任何Bin都会导致1 + k + j的额外大小,其中kj必须是有效的树大小。可以看出,这只会产生奇数大小的树木。

因此,我们可以在继续之前丢弃任何无效的Int

> genTrees n | even n || n <= 0 = []
> genTrees n =

现在我们知道我们n是奇数,至少有三个。因此,我们必须使用Bin作为其他树的根。其他树木?那么,还记得上面的公式吗?我们需要生成两个大小为jk的新树,以便1 + j + k = n。幸运的是,我们有一个生成这些树的函数,称为genTrees。我们可以将所有内容组合在一个列表中:

>   [Bin l r | i <- [1,3..n-1], l <- genTrees i, r <- genTrees (n - 1 - i)]

锻炼

  • 证明列表推导中所有使用的大小都是有效的,包括生成的树大小以及中间树大小。
  • 虽然第二段提供了一些动机,但它没有提供有效树木必须具有奇数大小的完整证据。证明该陈述。
  • 现在只计算Tip的大小。什么是现在有效的树大小?
  • 重写上面的算法,以便生成只有Tip s对大小有贡献的树(毕竟,只有它们有有效负载)。

答案 1 :(得分:3)

好吧我猜有些人不喜欢我试图导致解决方案的方式,所以没有进一步的原因:这里是一个

getTrees :: Int -> [Tree Bool]
getTrees 1 = [Tip True, Tip False]
getTrees n = do
  leftSize <- [0..n-2]
  let rightSize = (n-1) - leftSize
  left <- getTrees leftSize
  right <- getTrees rightSize
  return $ Bin left right

注意:

你可以在这里看到,你会遇到大小合适的树的问题,因为那些会在某个时间到达getTrees 0,这会拉leftSize <- [0..(-2)]并在那里以空列表结束