获取二叉树并按顺序打印其值的函数

时间:2012-11-18 12:00:59

标签: haskell

我正在编写一个函数来获取二叉树并以正确的顺序打印出它的值(按顺序颠倒)。我遇到的问题是,当我调用函数时,我一直得到一个非详尽的模式错误

 --k is the key and d is the value
 -- l is left tree and r is right tree
treeprint (Node l k d r)      =  treeprint l  ++ show k ++ show d ++ treeprint r 
treeprint Nil=""

1 个答案:

答案 0 :(得分:6)

似乎已经解决了你的问题,除了你需要一些括号和空格。

您的(当前)版本

我假设您正在使用

data Tree k d = Nil | Node (Tree k d) k d (Tree k d)

虽然你没有说。我将定义一两个示例树:

example1, example2 :: Tree Int String
example1 = Node (Node Nil 4 "Hello" Nil) 7 "there" (Node Nil 21 "hi" Nil)
example2 = Node example1 34 "well" (Node Nil 55 "This" (Node (Node Nil 73 "one's" Nil) 102 "much" (Node Nil 132 "bigger" Nil)))

你的功能

treeprint (Node l k d r) =  treeprint l  ++ show k ++ show d ++ treeprint r 
treeprint Nil = ""

编译好但是因为没有空格或括号,输出很混乱:

*Main> putStrLn $ treeprint example1
4"Hello"7"there"21"hi"
*Main> putStrLn $ treeprint example2
4"Hello"7"there"21"hi"34"well"55"This"73"one's"102"much"132"bigger"

它按顺序排列,但是压在一起,树结构消失了。

更多括号,更多空格,更清晰

让我们用每个树周围的括号和空格重写它:

tree_print (Node l k d r) = " (" ++ treeprint l  ++ show k ++ ":" ++ show d ++ treeprint r ++ ") "
tree_print Nil = ""

所以现在更清楚了:

*Main> putStrLn $ tree_print example1
 ( (4:"Hello") 7:"there" (21:"hi") ) 
*Main> putStrLn $ tree_print example2
 ( ( (4:"Hello") 7:"there" (21:"hi") ) 34:"well" (55:"This" ( (73:"one's") 102:"much" (132:"bigger") ) ) ) 

展平树并获得更多括号!

也许你不想要括号,因为顺序打印是为了展平树。你可以保留空格和:,它会起作用。或者,定义

toList :: Tree k d -> [(k,d)]
toList Nil = []
toList (Node t1 k d t2) = toList t1 ++ (k,d):toList t2

这意味着您可以将Show实例用于列表:

*Main> toList example1
[(4,"Hello"),(7,"there"),(21,"hi")]
*Main> toList example2
[(4,"Hello"),(7,"there"),(21,"hi"),(34,"well"),(55,"This"),(73,"one's"),(102,"much"),(132,"bigger")]

更漂亮

以下是使用pretty-tree库中的Data.Tree.Pretty打印树的方法。

我必须做一些导入:

import qualified Data.Tree as T
import Data.Tree.Pretty

我已导入Data.Tree限定,因为它还定义了数据构造函数Node。这意味着当我指的是导入的树时我会使用T.Node,但是当我指的是你的时候我只会使用Node

它使用玫瑰树(每个节点可以拥有尽可能多的子树):

data Tree a = Node {
        rootLabel :: a,         -- ^ label value
        subForest :: Forest a   -- ^ zero or more child trees
    }

并定义我将使用的drawVerticalTree :: Tree String -> String。 我们需要做的就是将您的树转换为此树,我们将开展业务:

toTree :: (Show k,Show d) => Tree k d -> T.Tree String
toTree Nil = T.Node "-" []
toTree (Node t1 k d t2) = T.Node (show k ++ ":" ++ show d) [toTree t1,toTree t2]

现在让我们展示(制作一个字符串)并打印(IO monad中的输出):

showtree :: (Show k, Show d) => Tree k d -> String
showtree = drawVerticalTree.toTree

printtree :: (Show k, Show d) => Tree k d -> IO ()
printtree = putStrLn.('\n':).showtree

这给出了很好的输出:

*Main> printtree example1

    7:"there"     
        |         
     ---------    
    /         \   
4:"Hello"  21:"hi"
    |         |   
    --        --  
   /  \      /  \ 
   -  -      -  - 

使用稍微大一些的例子,相当优雅地应对:

*Main> printtree example2

                   34:"well"                   
                       |                       
         ------------------------              
        /                        \             
    7:"there"                55:"This"         
        |                        |             
     ---------       -------------             
    /         \     /             \            
4:"Hello"  21:"hi"  -         102:"much"       
    |         |                   |            
    --        --            ------------       
   /  \      /  \          /            \      
   -  -      -  -      73:"one's"  132:"bigger"
                           |            |      
                           --           --     
                          /  \         /  \    
                          -  -         -  -