2016-12-12 2 views
0

Я хотел бы написать функцию, которая при задании n будет точно добавлять количество листьев без вырождения дерева. Что-то вроде этого:Как управлять деревьями в Haskell

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.

например. добавление 2 листов adding 2 leaves

+2

Что это означает, чтобы добавить 3 листа к произвольному дереву? Можете ли вы нарисовать его? –

+0

Я добавил ссылку на картинку. Извините, это немного дерьмово. – SmokedHering

+1

«без дегенерации дерева» - что это значит, точно? Нужно ли каким-то образом балансировать дерево? – chi

ответ

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

Большое спасибо за подробный ответ. Реально, просто один вопрос. Для лучшего понимания я упростил функцию addTree для себя: 'addTree L = (NLL)' 'addTree (N lr) = if (height l> height r) then (N l (addTree r) else (N (add l) r) '. Это должно добавить только один (NLL) на стороне emptier. Но он всегда возвращает ошибку синтаксического анализа на другое. Почему? – SmokedHering

+0

Вам не хватает закрывающей круглой скобки в выражении' then'. – chepner

+0

Спасибо, вы помогли мне лучше понять деревья лучше. – SmokedHering

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 

Edit: «это дерево уже выродились - мы должны не вырождаться его.» < - Фактически это сменяет более простое решение для бюджетирования:

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

Я не думаю, что это получается совершенно правильно. Рассмотрим дерево, подобное 'NL (NL (NL (NL (NL (NL (NL (NLL))))) '.' budget' присваивает все доступные узлы левому поддереву, не сохраняя ни одного для правого поддерева, оставляя дерево неуравновешенным. – chepner

+0

Это дерево уже вырождено - мы предполагается, что он не дегенерирует его. – Gurkenglas

+0

Вопрос не говорит ничего о том, что данное дерево сбалансировано, хотя это может быть разумным предположением, которое осталось неустановленным. – chepner

Смежные вопросы