Haskell: сведение двоичного дерева

Я думал о сведении двоичного дерева к списку для последующей обработки

Сначала я подумал об использовании (++)для соединения левой и правой ветвей, но потом подумал, что в худшем случае это займет O(n^2)время.

Затем я подумал о построении списка в обратном порядке, используя (:)для добавления к началу за линейное время. должен ждать, пока все дерево не будет пройдено, прежде чем оно сможет начать свертываться, и, следовательно, не может использовать слияние списков.

Затем я придумал следующее:

data Tree a = Node a (Tree a) (Tree a) | Tip

flatten :: Tree a -> [a]
flatten x = (flatten' x) []

flatten' :: Tree a -> [a] -> [a]
flatten' (Node x left right) l = (flatten' left (x:(flatten' right l)))
flatten' Tip l = l

main = 
  putStrLn $ show $ flatten $ 
    (Node 2 (Node 1 Tip Tip) (Node 4 (Node 3 Tip Tip) Tip))

Будет ли это работать за O(n)раз, занимать «пространство стека» не более, чем пропорционально наибольшей глубине дерева, и можно ли его объединить с потребляющей функцией (т. е. исключить промежуточный список)? "правильный" способ сплющить дерево?

13
задан Will Ness 15 May 2012 в 09:37
поделиться