给定以下数据类型定义:
data FormTree = Empty | Node FormTree FormTree deriving Show
我想编写一个函数,它生成一个无限列表,其中包含按长度排序的所有可能的树,例如节点数量。
下面的代码几乎满足了我的需要,但它只是通过每次插入额外的节点来使右侧的树下降,但我需要它在两侧之间交替。
allPossibleTrees :: [FormTree]
allPossibleTrees = Empty : [Node x y | x <- recursive, y <- recursive]
where recursive = allPossibleTrees
执行中
take 5 allPossibleTrees
给出:
[Empty,Node Empty Empty,Node Empty (Node Empty Empty),Node Empty (Node Empty (Nodes Empty Empty)),Node Empty (Node Empty (Node Empty (Node Empty Empty)))]
但它应该是这样的:
[Empty,Node Empty Empty,Node (Node Empty Empty) Empty,Node Empty (Node Empty Empty),Node (Node Empty Empty) (Node Empty Empty)]
最佳答案
这是一个很好的技巧,让人想起标准的斐波那契数字技巧。我们将建立一个惰性列表;列表中的每个成员都是具有给定节点数的所有树的列表。只有一棵没有节点的树,空
,这将作为我们的基本情况。要构建具有 n
个节点的所有树,我们假设我们已经知道如何使用 0
、1
、2 构建树
, ..., n-1
个节点。然后,我们将不确定地选择总和为 n-1
的配对,并将一个 Node
放在顶部。
在代码中:
import Control.Monad
import Data.List
sizes :: [[FormTree]]
sizes = [Empty] : (map go . drop 1 . inits) sizes where
go smaller = do
(ls, rs) <- zip smaller (reverse smaller)
liftM2 Node ls rs
然后,如果需要的话,我们可以简单地定义allPossibleTrees = concatsized
。前几个条目:
*Main> mapM_ print (take 4 sizes)
[Empty]
[Node Empty Empty]
[Node Empty (Node Empty Empty),Node (Node Empty Empty) Empty]
[Node Empty (Node Empty (Node Empty Empty)),Node Empty (Node (Node Empty Empty) Empty),Node (Node Empty Empty) (Node Empty Empty),Node (Node Empty (Node Empty Empty)) Empty,Node (Node (Node Empty Empty) Empty) Empty]
我们可以进行快速健全性检查:
*Main> take 10 (map length sizes)
[1,1,2,5,14,42,132,429,1430,4862]
...这确实是前十个 Catalan numbers ,所以我们可能是对的!
关于haskell - 生成所有可能的树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28100650/