簡體   English   中英

Haskell中樹數據結構的鄰接列表

[英]Adjacency list of a tree data structure in Haskell

我在Haskell中定義了以下抽象數據類型:

data Trie = Leaf
          | Node [(Char, Trie)]
          deriving (Eq)

Node類型是元素列表(c, t) ,其中c是從當前節點到t的邊的標簽。

現在我要打印出樹的鄰接列表。 具體來說,我需要每行打印一個邊,其中邊的格式為:

n1 n2 c

n1是源, n2是目標, c是邊緣的標簽。

我可以用我的根節點打印邊緣

instance Show Trie where
    show = show' 2 1
        where show' _ _ Leaf = ""
              show' next n1 (Node ts) = unlines $ zipWith (\n2 (c, _) ->
                                                           show n1 ++ " " ++ show n2 ++ " " ++ show c)
                                                    [next..] ts

但現在我被困在如何遞歸打印孩子們。 特別是,如何為子節點編號?

標記節點非常簡單,因為GHC將為您完成所有繁重的任務:

{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}

import qualified Data.Traversable as T
import qualified Data.Foldable as F 
import Control.Monad.State 

data Trie a = Leaf a | Node a [(Char, Trie a)] 
  deriving (Eq, Functor, F.Foldable, T.Traversable)

number :: Trie a -> Trie (a, Int)
number = flip evalState 1 . T.mapM (\x -> state $ \n -> ((x,n),n+1))

至於打印特里,我擔心我不太理解所需的輸出。

我想出了這個解決方案:

import Data.List (foldl')

enum :: Int -> Trie -> ([(Int,Int,Char)],Int)
enum x Leaf = ([],x+1)
enum x (Node pairs)
  = let go (acc,y) (c,t) = (acc',y')
          where acc' = [(x,y,c)] ++ edges ++ acc
                (edges,y') = enum y t
    in foldl' go ([],x+1) pairs

enum接受一個起始id和一個Trie並返回一個邊列表和下一個可用的id。

-- some examples:

leafs xs = [ (c,Leaf) | c <- xs ]
t1 = Node $ leafs "XYZ"
t2 = Node [('W', t1)]
t3 = Node $ [('A',t2)] ++ leafs "BC"

enum 1 t1 -- ([(1,4,'Z'),(1,3,'Y'),(1,2,'X')],5)
enum 1 t2 -- ([(1,2,'W'),(2,5,'Z'),(2,4,'Y'),(2,3,'X')],6)
enum 1 t3 -- ([(1,8,'C'),(1,7,'B'),(1,2,'A'),(2,3,'W'),(3,6,'Z'),(3,5,'Y'),(3,4,'X')],9)

這是我的嘗試:

data Trie c =
    Leaf
  | Node [(c, Trie c)]
  deriving (Eq)

instance Show c => Show (Trie c) where
  show = show' 1 (\_ -> "\n") where
      show' next cc Leaf = show next ++ "\n” ++ cc (next + 1)
      show' next cc (Node []) = show next ++ "\n” ++ cc (next + 1)
      show' next cc (Node [(c,t)] = show c ++ "(" ++ show next ++ ")” ++ show' (next+1) cc t
      show' next cc (Node (x:xs)) = show' next (\n -> show' n cc $ Node xs) (Node [x])

我使用延續傳遞方式來跟蹤狀態。 應該有一種方法可以使代碼成為monadic,或者使用拉鏈代替。

您可以更改葉子或節點的特定位,具體取決於您是否需要編號(通過更改next + 1部分)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM