如何在Haskell中操纵树木

时间:2016-12-12 14:46:39

标签: haskell data-structures tree binary-tree

我想写一个函数,给定一个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的偶数。

e.g。添加2个叶子adding 2 leaves

2 个答案:

答案 0 :(得分:1)

首先,您需要一个辅助函数来确定树的哪一侧“更空”。

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))

答案 1 :(得分:1)

更懒惰的方法也不必保持遍历树的二次时间(尽管仍然采用次优的O(n * log(n)),并且会给你的示例的右半部分“第一”,因为它更空虚):

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

编辑:“那棵树已经退化 - 我们不应该贬低它。” < - 事实上,这让位于更简单的预算解决方案:

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')