从预订和订单列表

时间:2017-09-06 17:07:06

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

您好我正在尝试重建一棵二叉树,我几乎得到了它,除了它给我一个错误,我不知道为什么

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

2 个答案:

答案 0 :(得分:2)

此行的运行时失败:

Just rootInd = elemIndex root inOrd
在运行示例输入时,

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

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

答案 1 :(得分:1)

@chepner发现了错误。如果您想知道将来如何自行查找和修复这些错误,您可能会发现以下答案有用......

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

> 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。 (对于您的测试用例,错误消息略有不同,但根本原因是相同的。)

这会将问题确定为buildTree定义中right的第二个参数 - 值2不应包含在(空)右树中。从那里,很容易发现并修复right定义中的拼写错误,所以它写着:

read = buildTree rigthPreOrd rightInOrd

在修复之后,事情似乎正常。