【问题标题】:Postorder traversal of binary tree with recursive data type递归数据类型二叉树的后序遍历
【发布时间】:2019-04-11 15:17:00
【问题描述】:

我正在尝试为递归数据类型的后序遍历创建一个函数,该函数创建一个二叉树,其中示例可以创建尽可能多的子叶。我尝试将节点设置为 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 不会绑定,为什么用 appends 调用列表中的 postord 不会编译右节点、左节点和 root 中每个节点的列表.

【问题讨论】:

  • 在我看来,您在传递子树列表的版本中混合了一个真正的二叉树(它会有一个看起来完全不同的data 声明)。 (要成为真正的二叉树,该列表只会有 2 个元素,但这种类型不会强制执行此操作,您已经给出了 3 个的示例。)
  • 后序遍历是处理分支的所有子项,然后处理分支中的值。但是,您不会将值存储在分支中,而只是存储在叶子中,因此后序或前序遍历的想法对于这种结构毫无意义。您编写的代码实际上会做的(如果编写正确的话)是将第三个孩子,第四个孩子等按顺序处理到最后一个孩子,然后是第一个孩子,然后是第二个孩子。我怀疑这就是你想要的。

标签: haskell


【解决方案1】:

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]

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 是什么意思?我可以用别的东西代替它吗?我不熟悉它。
    • @Francis <$>fmap 的中缀别名。它的用法相当于fmap postord right
    • 有什么方法可以将它写成辅助函数而不是使用 ?它对我来说太高级了,我想知道我是否可以展示它的工作方式而不是调用 fmap 的 ?
    • @Francis 你熟悉map吗?对于列表,fmap = map
    • 我同意@chepner 的回答。
    猜你喜欢
    • 2016-05-01
    • 2010-11-20
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 2013-07-23
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多