Haskell: 二叉树和Catalan数
理论
Catalan数:C(2n, n)=(2n)!/n!/n!
关于n个节点二叉树种类数和Catalan数的关系,可阅读这篇博客。
Haskell实现:二叉树的定义
data Tree = Leaf | Node Tree Tree deriving Show
-- 这里的leaf不是代表叶子节点,而是代表根本没有
-- 这里的node不需要预先定义,而只是一个名字;这个名字本身没有任何意义,出现在模式匹配里面才存在意义。
-- 如果结点需要包含信息,也是用模式匹配的方式追加在里面。比如:
-- data Tree = Leaf | Node Int Tree Tree deriving Show -- 注意里面的int
以上定义了“结点不需要包含任何信息”的二叉树。
Haskell实现:打印二叉树的信息
为刚刚定义的二叉树数据结构定义一个打印其信息的函数:
-- brace的几种定义方式
-- 1.空的分支用没有表示,非空的分支用括号括起来
brace :: Tree -> String
brace Leaf = ""
-- brace Leaf = "*" -- 空的分支用*表示
brace (Node lTree rTree) = "(" ++ brace lTree ++ "," ++ brace rTree ++ ")"
-- 2.左括号跟左子树,右括号跟右子树
-- 这种定义方式对应的实际情景:n对括号,合理的括号嵌套有多少种情形,这个问题的答案也是Catalan数。
brace :: Tree -> String
brace Leaf = ""
brace (Node lTree rTree) = "(" ++ brace lTree ++ ")" ++ brace rTree
树的打印方式千变万化,根据需要的视觉效果自己把握。
Haskell实现:Catalan数的求解
求解“包含n个节点的二叉树的种类数”:使用分治法求解,f(n) = f(n-1)f(0) + f(n-2)f(1) + f(n-3)f(2) + ... + f(1)f(n-2) + f(n-1)f(0)
。
trees :: Int -> [Tree] -- 返回所有不重复的包含n个结点的二叉树的列表
trees 0 = [Leaf]
trees n = [Node lTree rTree | l <- [0 .. n-1], lTree <- trees l, rTree <- trees (n-1-l)]
列表长度即为所求:执行length $ trees n
。
执行map brace $ trees n
,返回一个列表,展示所有的树的表示。
参考:魔力Haskell