具有递归数据类型的二叉树的后置遍历

时间:2019-04-11 15:17:00

标签: haskell

我正在尝试为递归数据类型的后遍历创建一个函数,该函数创建一个二叉树,其中示例可以创建尽可能多的子叶子。我试图将节点设置为left:root:right,但是错误无法识别它们-但是,它会识别(y:ys)。无论我使用()或[]还是周围没有任何内容,它都将root识别为Int。我想念什么?

这是数据类型以及一些易于测试的示例:

data BiTree a = L a
            | N [BiTree a]

ex1 :: BiTree Int
ex1 = N [(L 1),(L 1),(L 3)]

ex2 :: BiTree Int
ex2 = N [(L 1),(N[(L 2),(L 3)]),(L 4)]

这是我写的代码:

postord :: BiTree a -> [Int]
postord (L x)                  = [x]
postord (N (left:root:right))  = postord (N right) ++ postord (N left) ++ [root]

这是错误:

* Couldn't match expected type `Int' with actual type `BiTree a'
* In the expression: root
  In the second argument of `(++)', namely `[root]'
  In the second argument of `(++)', namely
    `postord (N left) ++ [root]'
* Relevant bindings include
    right :: [BiTree a] (bound at try.hs:21:23)
    root :: BiTree a (bound at try.hs:21:18)
    left :: BiTree a (bound at try.hs:21:13)
    postord :: BiTree a -> [Int] (bound at try.hs:20:1)
|
21 | postord (N (left:root:right)) = postord (N right) ++ postord (N left) ++ [root]
|                                                         ^^^^

我不明白为什么left:right:root不绑定,为什么用追加调用列表中的postord不会按原样编译右节点,左节点和root中每个节点的列表

2 个答案:

答案 0 :(得分:1)

N没有特定的左,右子级,并且肯定没有任何可区分的根值; just 有一个任意的孩子列表。

BiTree仅将值存储在叶子中。与N值唯一相关的是将postord映射到每个孩子,并将结果串联到一个列表中。 (因此,预订前,订单中和订单后遍历之间没有真正的区别。)

postord :: BiTree a -> [a]
postord (L x)         = [x]
postord (N children)  = concatMap postord children

现在,如果您有一个 did 在内部节点中存储值的类型,则您的类型可能看起来像

data BiTree a = L a | N a [BiTree a]

然后,您的后订单遍历必须考虑存储在内部节点中的值,类似于您先前的尝试。

postord :: BiTree a -> [a]
postord (L x) = [x]
postord (N v children) = concatMap postord children ++ [v]

将单个值添加到较长的列表并不理想,但这是另一个问题的问题。

答案 1 :(得分:0)

不知道我是否理解您的问题,但是呢:

postord :: BiTree a -> [a]
postord (L x) = [x]
postord (N cs) = concatMap postord cs