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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有递归数据类型的二叉树的后序遍历相关的知识,希望对你有一定的参考价值。

我正在尝试为递归数据类型的后序遍历创建一个函数,该函数创建一个二叉树,其中示例可以创建尽可能多的子叶。我试图将节点设置为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]
|                                                         ^^^^

我不明白为什么离开:右:root不会绑定,为什么在列表中调用带有追加的postord将不会按原样编译右节点,左节点和root中的每个节点的列表。

答案

N没有特定的左右儿童,它当然没有任何明显的根值;它只有一个任意的儿童名单。

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

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

现在,如果您有一个在内部节点中存储值的类型,那么您的类型可能是这样的

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]

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

另一答案

不知道我是否理解你的问题,但是这个怎么样:

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

以上是关于具有递归数据类型的二叉树的后序遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的后续遍历是啥意思啊?

二叉树的后序遍历(非递归)

LeetCode 145. 二叉树的后序遍历 (用栈实现后序遍历二叉树的非递归算法)

Java集合与数据结构 二叉树

Java集合与数据结构 二叉树

Java集合与数据结构 二叉树