2015-04-09 4 views
1

Каков наилучший способ построить дерево из списка? Мне интересно найти функциональный способ решения этой проблемы. Какие пакеты и модули могут вам помочь?Построение дерева по определенному списку

Этот вопрос касается фактического хранения исходной структуры в дереве, не только отображения его как дерева.

Первоначальная структура:

[[1, 1, 1, 0.5], 
[1, 1, 2, 0.5], 
[1, 1, 3, 0.5], 
[1, 1, 4, 0.5], 
[1, 1, 5, 0.5], 
[1, 2, 1, 0.5], 
[1, 2, 2, 0.5], 
[1, 2, 3, 0.5], 
[1, 2, 4, 0.5], 
[1, 2, 5, 0.5]] 

Результат (набран руками):

Node 1 
    Node 1 
     Node 1 
      Node 0.5 
     Node 2 
      Node 0.5 
     Node 3 
      Node 0.5 
     Node 4 
      Node 0.5 
     Node 5 
      Node 0.5 
    Node 2 
     Node 1 
      Node 0.5 
     Node 2 
      Node 0.5 
     Node 3 
      Node 0.5 
     Node 4 
      Node 0.5 
     Node 5 
      Node 0.5 

Спасибо!

+4

Когда вы говорите, строите дерево, вы спрашиваете о его хранении в древовидной структуре или фактическом отображении его как дерева, как в вашем вопросе? –

+2

Я спрашиваю о фактическом хранении исходной структуры в дереве. Спасибо. Добавлен вопрос. – SDmitry

ответ

4

Определить некоторую структуру дерева

data T a = T a [T a] deriving Show 

и вставить каждую строку в

insert :: Eq a => [T a] -> [a] -> [T a] 
insert ts [] = ts 
insert [] (x:xs) = [T x $ insert [] xs] 
insert ([email protected](T n ns):ts) [email protected](x:xs) 
    | n == x = (T n (insert ns xs)):ts 
    | otherwise = t: insert ts xss 

многих строк дерева

fromList :: Eq a => [[a]] -> [T a] 
fromList = foldl insert [] 

для печати

showTree :: Show a => [T a] -> [String] 
showTree ts = concat [ ("Node " ++ show n): map (" "++) (showTree ns) | T n ns <- ts] 

Пример

main = do 
    putStrLn $ unlines $ showTree $ fromList 
     [[1, 1, 1, 0.5], 
     [1, 1, 2, 0.5], 
     [1, 1, 3, 0.5], 
     [1, 1, 4, 0.5], 
     [1, 1, 5, 0.5], 
     [1, 2, 1, 0.5], 
     [1, 2, 2, 0.5], 
     [1, 2, 3, 0.5], 
     [1, 2, 4, 0.5], 
     [1, 2, 5, 0.5]] 

результате

Node 1.0 
    Node 1.0 
    Node 1.0 
     Node 0.5 
    Node 2.0 
     Node 0.5 
    Node 3.0 
     Node 0.5 
    Node 4.0 
     Node 0.5 
    Node 5.0 
     Node 0.5 
    Node 2.0 
    Node 1.0 
     Node 0.5 
    Node 2.0 
     Node 0.5 
    Node 3.0 
     Node 0.5 
    Node 4.0 
     Node 0.5 
    Node 5.0 
     Node 0.5 
+0

Точно! Благодарю. Исходные списки будут похожи на пути в дереве, необходимом для их вставки? – SDmitry

+0

да, следуйте по пути и вставьте, если не найдете :) – josejuan

3

Это иногда называют розы дерево, Data.Tree из упаковки контейнеров (который поставляется с GHC) обеспечивают определение типа и некоторые инструменты для обработки тех (очень простой, но поскольку у вас их уже есть ...).

Вы можете выполнить задание, вставив несколько раз каждый путь, но это не будет использовать структуру вашего списка. Если вам гарантировано, что он будет отсортирован, вы можете напрямую сгенерировать Дерево (или, скорее, Лес, поскольку нет гарантии, что все ваши подсписчики имеют одну и ту же голову), группируя подсписку с помощью аналогичных головок, затем рекурсивно создавая подлесы из хвостов:

fromSortedList :: (Eq a) => [[a]] -> Forest a 
fromSortedList [] = [] 
fromSortedList xs = concatMap fromOneGroup . groupBy eq $ xs 
    where 
    eq (x:_) (y:_) = x == y 
    eq _  _  = False 
    fromOneGroup ([] : _) = [] 
    fromOneGroup xs  = [Node (head . head $ xs) (fromSortedList . map tail $ xs)] 

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

+0

Спасибо! Этот путь тоже интересен. – SDmitry

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