【问题标题】:Printing Binary Tree per Layer in a List打印列表中每层的二叉树
【发布时间】:2010-11-01 12:05:03
【问题描述】:

该函数应将层中参数树的标记打印为层列表。每一层的节点和叶子标记是从左到右列出的,即哪一层是最左边的节点,列表的第一个元素,最右边的节点是列表的最后一个元素。 Ord 类型的参数表示是按照从小到大的升序(TopDown)还是从大到小的降序(BottomUp)下发

data Tree = Leaf Integer | Node Integer Tree Tree

type Layer = [Integer]

data Ord = BottomUp | TopDown

wLayer :: Tree -> Ord -> [Layer] 

示例 1:我们使用参数调用函数 wLayer
wLayer (Node 1 (Node 2 (Leaf 21) (Leaf 22)) (Node 3 (Leaf 31) (Leaf 32))) TopDown 结果:[[1],[2,3],[21,22,31,32]]

示例 2: wLayer (节点 1 (节点 2 (叶子 21) (叶子 22)) (节点 3 (叶子 31) (叶子 32))) 自底向上 结果:[[21,22,31,32],[2,3],[1]]

我该如何实现这个?

编辑

data Tree = Leaf Integer
          | Node Integer Tree Tree
type Layer = [Integer]
data Ord   = BottomUp | TopDown

writeLayer :: Tree -> Ord -> [Layer]
writeLayer Leaf x = [x]
writeLayer (Node x lt rt) BottomUp = (writeLayer rt BottomUp) ++ [x] ++ (writeLayer lt BottomUp)
writeLayer (Node x lt rt) TopDown  = [x] ++ (writeLayer lt TopDown) ++ (writeLayer rt TopDown)

这是我的程序,但它不起作用我该如何解决它?

【问题讨论】:

  • 到目前为止你尝试了什么?

标签: haskell


【解决方案1】:

这是完成此任务的简单方法。它获取一个级别的所有节点并从中提取整数值,然后在这些相同节点的所有子节点上递归。之后,您匹配 Ord 以确定是否需要反转列表。

writeLayer t o =
    case o of
        BottomUp -> reverse $ makeLayer [t]
        TopDown -> makeLayer [t]
    where
        extract (Node i _ _) = i
        extract (Leaf i) = i
        children (Node _ a b) = [a, b]
        children _ = []
        makeLayer [] = []
        makeLayer ts = map extract ts : (makeLayer $ concat $ map children ts)

【讨论】:

    【解决方案2】:

    一些提示:

    • TreeLeaf 的情况很简单
    • BottomUpTopDown 的区别似乎是你是否把Layers 的列表倒过来
    • TreeNode 时,您将不得不递归子树并以某种方式组合结果

    编辑:好的,让我们专注于其中的第一个。

    你对这种情况的等式是

    writeLayer Leaf x = [x]
    

    首先,Leaf x 需要放在括号中,因为它是单个 Tree 值。

    writeLayer (Leaf x) = [x]
    

    其次,等式需要反映writeLayer带有两个参数(如上所述,它只需要一个)。使用Leaf 值,我们不关心返回结果的顺序——无论哪种方式,我们都会给出相同的答案——但我们仍然必须采用参数。我们使用_ 来表示我们不在乎这个参数并且不会使用它。

    writeLayer (Leaf x) _ = [x]
    

    第三,[x]Integers 的(单元素)列表 --- 但我们应该返回Layers 的列表。我相信你可以弄清楚如何解决这个问题。

    最后,注意电脑给你的错误信息。了解他们。

    【讨论】:

      【解决方案3】:

      保罗的回答给出了水平顺序遍历的核心定义 - 展开到列表。 (练习:用Data.List.unfoldrmakeLayer。)这也是我最喜欢的方式;见The Underappreciated Unfold

      但它也可以递归地完成 - 作为树上的折叠。这些类比列表中的foldr 定义如下:

      foldt :: (Integer->a) -> (Integer->a->a->a) -> Tree -> a
      foldt f g (Leaf n)     = f n
      foldt f g (Node n t u) = g n (foldt f g t) (foldt f g u)
      

      然后通过简单的树折叠给出级别顺序遍历,可能有reverse

      wLayer :: Tree -> Order -> [Layer] 
      wLayer t o = (if o==BottomUp then reverse else id) (foldt single glue t)
      

      我冒昧地将您的标志类型 Order 重命名为无效名称冲突,并使其成为 Eq 的实例:

      data Order = BottomUp | TopDown deriving Eq
      

      函数single进行叶子的层序遍历:

      single :: Integer -> [Layer]
      single n = [[n]]
      

      glue 将标签和两个子节点的遍历组合成一个节点的遍历:

      glue :: Integer -> [Layer] -> [Layer] -> [Layer]
      glue n x y = [n] : longzipwith (++) x y
      

      关键成分是函数longzipwith,它类似于zipWith,除了(i)结果的长度是较长参数的长度,而不是较短参数的长度,因此(ii)二元运算符有成为a->a->a:

      longzipwith :: (a->a->a) -> [a] -> [a] -> [a]
      longzipwith f (a:x) (b:y) = f a b : longzipwith f x y
      longzipwith f x     []    = x
      longzipwith f []    y     = y
      

      【讨论】:

        【解决方案4】:

        这是我的程序呢

        data Tree = Leaf Integer
            | Node Integer Tree Tree
        type Layer = [Integer]
        data DOrd   = BottomUp | TopDown
        writeLayer :: Tree -> DOrd -> [Integer]
        writeLayer (Leaf x) _ = [x]
        writeLayer (Node x lt rt) BottomUp = (writeLayer rt BottomUp) ++ [x] ++ (writeLayer lt BottomUp)
        writeLayer (Node x lt rt) TopDown  = [x] ++ (writeLayer lt TopDown) ++ (writeLayer rt TopDown)
        

        来电:

        *Main> writeLayer (Node 1 (Node 2 (Leaf 21) (Leaf 22)) (Node 3 (Leaf 31) (Leaf 32))) TopDown
        [1,2,21,22,3,31,32]
        *Main> writeLayer (Node 1 (Node 2 (Leaf 21) (Leaf 22)) (Node 3 (Leaf 31) (Leaf 32))) BottomUp
        [32,3,31,1,22,2,21]
        

        但我想先拿:[[1],[2,3],[21,22,31,32]]

        秒:[[21,22,31,32],[2,3],[1]]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多