我想写一个函数,给定一个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个叶子
答案 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')