我正在尝试创建大小为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的树的方法。
答案 0 :(得分:4)
首先让我们从简单的开始:大小为1的树:
> getTrees :: Int -> [Tree Bool]
> genTrees 1 = [Tip True, Tip False]
现在,我们必须考虑更多Int
s。那么2
呢?事实证明,如果Bin
和Tip
都增加了大小,则不存在任何大小为2的树。任何Bin
都会导致1 + k + j
的额外大小,其中k
和j
必须是有效的树大小。可以看出,这只会产生奇数大小的树木。
因此,我们可以在继续之前丢弃任何无效的Int
:
> genTrees n | even n || n <= 0 = []
> genTrees n =
现在我们知道我们n
是奇数,至少有三个。因此,我们必须使用Bin
作为其他树的根。其他树木?那么,还记得上面的公式吗?我们需要生成两个大小为j
和k
的新树,以便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)]
并在那里以空列表结束