如何在 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')
我想编写一个函数,给定一个 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')