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