如何在 Haskell 中操纵树

How to manipulate trees in Haskell

我想编写一个函数,给定一个 n 将准确地添加叶子的数量而不会使树退化。像这样:

data SimpleT= L | N SimpleT SimpleT deriving Show

和 addTree 定义为:

addTree::Int->SimpleT->SimpleT
addTree n (N left right) = something

但我做不对。到目前为止我唯一有效的方法是在每片叶子上添加一个 (N L L ):

 addTree2  L = (N L L)
 addTree2  (N left right)= N (addTree2  left)(addTree2  right)

如何正确添加 'n'? n 只允许偶数。

例如添加 2 个叶子

首先,您需要一个辅助函数来确定树的哪一侧 "emptier"。

height :: SimpleT -> Int
height L = 0
height (N l r) = 1 + max (height l) (height r)

那么,只需要一次向空的一侧添加2片叶子(即向空的一侧添加2片叶子,然后将n-2片叶子添加到结果树中)。

-- Warning: partial function, not defined for odd n
addTree :: Int -> SimpleT -> SimpleT
addTree 0 t = t
addTree n L = addTree (n - 2) (N L L)
addTree n (N l r) = addTree (n - 2) (if height l > height r
                                     then (N l (addTree 2 r))
                                     else (N (addTree 2 l) r))

更懒惰的方法也不必在二次时间内遍历树(尽管仍然需要次优的 O(n*log(n)),并且会给出示例的右半部分 "first"因为它比较空):

size :: SimpleT -> Int
size L = 1
size (N l r) = size l + size r

addTree :: Int -> SimpleT -> SimpleT
addTree 0 t = t
addTree n L = addTree (n-1) (N L L)
addTree n (N l r) = let (u, v) = budget (size l) (size r) n in
  N (addTree u l) (addTree v r)

budget :: Int -> Int -> Int -> (Int, Int)
budget l r n = let
  l' = min (n+l) r -- Raise l to r from our budget n
  n' = n+l-l'
  r' = min (n'+r) l' -- Raise r to l from our budget n
  n'' = n'+r-r'
  n''' = div n'' 2
  in (l'-l+n''-n''', r'-r+n''') -- Divide our remaining budget fairly

编辑:"That tree is already degenerated - we are supposed not to degenerate it." <- 事实上,这让位于更简单的预算解决方案:

budget :: Int -> Int -> Int -> (Int, Int)
budget l r n = let (n', m) = divMod n 2
  in (if l>r then swap else id) (n'+m,n')