P54 - 定义二叉树

2026-09-07 00:00    #Haskell   #99题   #二叉树  

P54 - 定义二叉树

Binary trees

官方模块:Problems.P54 核心类型:Tree


← P53 归结原理 | P55 完全平衡二叉树 →


数据类型

二叉树要么为空,要么是一个携带值且恰有左右两棵子树的分支。

1data Tree a
2  = Empty
3  | Branch a (Tree a) (Tree a)
4  deriving (Eq, Show)
5
6leaf :: a -> Tree a
7leaf x = Branch x Empty Empty

类型参数 a 表示节点值类型;树的形状与节点值彼此独立。leaf 不是新构造器,只是常用结构的辅助函数。

示例树

 1tree1 :: Tree Char
 2tree1 = Branch 'a'
 3  (Branch 'b' (leaf 'd') (leaf 'e'))
 4  (Branch 'c' Empty (Branch 'f' (leaf 'g') Empty))
 5
 6tree2 :: Tree Char
 7tree2 = leaf 'a'
 8
 9tree3 :: Tree Char
10tree3 = Empty
11
12tree4 :: Tree Int
13tree4 = Branch 1 (Branch 2 Empty (leaf 4)) (leaf 2)

基础度量

方法一:treeSize 递归计数

1treeSize :: Tree a -> Int
2treeSize Empty          = 0
3treeSize (Branch _ l r) = 1 + treeSize l + treeSize r

treeHeight:递归取最大深度

1treeHeight :: Tree a -> Int
2treeHeight Empty          = 0
3treeHeight (Branch _ l r) = 1 + max (treeHeight l) (treeHeight r)

方法二:treeSize 显式栈

1treeSize :: Tree a -> Int
2treeSize tree = go [tree] 0
3  where
4    go [] acc = acc
5    go (Empty : rest) acc = go rest acc
6    go (Branch _ l r : rest) acc = go (l : r : rest) (acc + 1)

显式使用栈代替递归,遍历所有节点时计数。对于极深的树可以避免栈溢出。

方法三:treeSize 用 fold 风格

1treeSize :: Tree a -> Int
2treeSize = foldTree (\_ l r -> 1 + l + r)
3  where
4    foldTree :: (a -> Int -> Int -> Int) -> Tree a -> Int
5    foldTree _ Empty          = 0
6    foldTree f (Branch x l r) = f x (foldTree f l) (foldTree f r)

测试

1>>> treeSize tree1
27
3>>> treeHeight tree1
44
5>>> tree2 == leaf 'a'
6True

参考