您好我正在尝试重建一棵二叉树,我几乎得到了它,除了它给我一个错误,我不知道为什么
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
答案 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
在修复之后,事情似乎正常。