【问题标题】:Rebuild a binary tree from preorder and inorder lists从前序和中序列表重建二叉树
【发布时间】:2017-09-06 17:07:06
【问题描述】:

您好,我正在尝试重建一棵二叉树,我几乎成功了,但它抛出了一个错误,我不知道为什么

buildTree :: (Ord a, Eq a) => [a] -> [a] -> Tree a
buildTree [] [] = Empty
buildTree preOrd inOrd = Node root left right 
where root  = head preOrd
      left = buildTree leftPreOrd leftInOrd
      right = buildTree rigthPreOrd leftInOrd

      Just rootInd = elemIndex root inOrd
      leftPreOrd   = tail (take (rootInd + 1) preOrd)
      rigthPreOrd  = tail (drop rootInd preOrd)

      leftInOrd    = take rootInd inOrd
      rightInord   = drop (rootInd + 1) inOrd

当我使用它调用它时

buildTree [10,5,2,6,14,12,15] [2,5,6,10,12,14,15]

它向我抛出了这个:

Exception: reconstruir.hs:26:11-45: Irrefutable pattern failed for pattern Just rootInd

【问题讨论】:

  • 您将leftInOrd 而非rightInOrd 传递给计算右子树的buildTree 调用。

标签: haskell functional-programming binary-tree inorder preorder


【解决方案1】:

运行时在这一行失败:

Just rootInd = elemIndex root inOrd

elemIndex 在运行您的示例输入时返回Nothing,但您的代码说它将始终返回Just,因此运行时崩溃。你需要处理elemIndex root inOrd返回Nothing的情况。

也许更重要的是,您应该启用所有带有 -Wall flag 的警告以显示为编译器错误,这样您的代码就不会开始编译。

【讨论】:

  • 假设输入是同一棵树的有效遍历,应该能够证明elemIndex不会返回Nothing。我相信这是允许这种情况的代码中的错字。
  • 不过,这是一个很大的假设。我认为最好让这个函数返回 Maybe (Tree a) 以允许输入不正确的情况。
【解决方案2】:

@chepner 发现了错误。如果您想知道将来如何自己查找和修复此类错误,您可能会发现以下答案很有帮助...

首先,它有助于找到尽可能小的测试用例。通过几次尝试,让您的程序在 2 节点树上失败并不难:

> buildTree [5,2] [2,5]
Node 5 (Node 2 Empty Empty) (Node *** Exception: Prelude.head: empty list

现在,尝试手动跟踪buildTree [5,2] [2,5] 的评估。如果您手动评估此第一个 buildTree 调用,您会发现所涉及的变量具有值:

preOrd = [5,2]
inOrd = [2,5]
Just rootInd = Just 1

leftPreord = tail (take 2 [5,2]) = [2]
rightPreord = tail (drop 1 [5,2]) = []

leftInOrd = take 1 [2,5] = [2]
rigthInord = drop 2 [2,5] = []

root = 5
left = buildTree [2] [2]
right = buildTree [] [2]

一切看起来都很好,除了right,它试图用不兼容的前序表和中序表构建一棵树。这就是导致错误的原因,因为buildTree [] [2] 尝试获取空列表的head。 (您的测试用例的错误消息略有不同,但根本原因是相同的。)

这将问题定位为right 定义中buildTree 的第二个参数——值2 不应包含在(空)右树中。从那里,很容易发现并修复right 定义中的错字,因此它显示为:

read = buildTree rigthPreOrd rightInOrd

修复后,一切似乎都正常了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    相关资源
    最近更新 更多