Haskell 从边列表构造树:缺少叶节点
我编写了下面的代码来构造一棵树,该树具有给定的顶点以及顶点之间的连接列表Haskell 从边列表构造树:缺少叶节点,haskell,ghci,Haskell,Ghci,我编写了下面的代码来构造一棵树,该树具有给定的顶点以及顶点之间的连接列表 type Connection = (Int,Int) data Tree = Leaf Int | Node Int [Tree] deriving (Eq,Read,Show) makeTree :: Int -> [Connection] -> Tree makeTree x [] = Leaf x makeTree indx connections = Node indx otherTrees wh
type Connection = (Int,Int)
data Tree = Leaf Int | Node Int [Tree] deriving (Eq,Read,Show)
makeTree :: Int -> [Connection] -> Tree
makeTree x [] = Leaf x
makeTree indx connections = Node indx otherTrees where
otherTrees = [makeTree i cx | i <- directConnections, let cx = removeConnectionsTo indx connections]
directConnections = map (\(x,y) -> if (x == indx) then y else x) $ filter (\(x,y) -> x == indx || y == indx) connections
removeConnectionsTo :: Int -> [Connection] -> [Connection]
removeConnectionsTo indx = filter (\(x,y) -> x /= indx && y /= indx)
类型连接=(Int,Int)
数据树=叶Int |节点Int[树]派生(Eq,读取,显示)
makeTree::Int->[连接]->树
makeTree x[]=叶x
makeTree indx connections=节点indx otherTrees,其中
otherTrees=[makeTree i cx|i if(x==indx)那么y else x)$filter(\(x,y)->x==indx|y==indx)连接
removeConnectionsTo::Int->[Connection]->[Connection]
将连接移除到indx=filter(\(x,y)->x/=indx&&y/=indx)
出于某种原因,下面的输入给了我令人惊讶的不同结果:
maketree1[(1,2)、(1,3)]
给我Node 1[叶2,叶3]
maketree1[(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)]
给了我节点1[节点2[节点3[],节点4[],节点5[节点6[],节点7[].
我正在OS X 10.8.2上运行GHCi 7.4.1版
我不明白为什么我在第一个示例中两次得到了Leaf(正确),但在第二个示例中得到了子树列表为空的节点(不正确)。一个快速解决方法是,在决定是构建
Leaf
还是节点之前,只需检查其他树是否为空,例如
makeTree indx connections
| null otherTrees = Leaf indx
| otherwise = Node indx otherTrees
where ...
为了了解这里发生了什么,让我们添加一点工具:
import Debug.Trace
makeTree :: Int -> [Connection] -> Tree
makeTree ix cs | traceShow (ix, cs) False = undefined
makeTree x [] = ... -- leave rest of the function as before
现在将其加载到GHCi中,让我们看看递归调用是什么:
> import Control.DeepSeq
> (show $ makeTree 1 [(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)]) `deepseq` ()
(1,[(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)])
(2,[(2,3),(2,4),(5,6),(5,7)])
(3,[(5,6),(5,7)])
(4,[(5,6),(5,7)])
(5,[(2,3),(2,4),(5,6),(5,7)])
(6,[(2,3),(2,4)])
(7,[(2,3),(2,4)])
()
如您所见,第二个参数中的列表不是空的,这就是为什么它与函数的第一种情况不匹配的原因,因此您需要像我的示例中那样添加一些额外的检查,或者确保过滤掉其余的连接。您希望得到什么结果?第二个答案应该包含“叶3”而不是“节点3[]”等。我对这个问题投了否决票,因为标题没有帮助,内容读起来有点像“请修复我的代码”没有任何明确的调查证据等@BenMillwood:现在改进了标题和问题。你的解决方案奏效了,但我仍然不明白为什么我的解决方案没有奏效。调用函数时,函数声明是按声明顺序选择的,因此makeTree x[]=Leaf x
应该首先匹配,不是吗?它不匹配,因为第二个参数中的列表不是空的。在向下到节点的路径上,从列表中删除的唯一连接是提到其祖先的连接,因此,例如,当您到达makeTree 7
时,连接仍然有[(2,3)、(2,4)]
在里面。啊,我花了一段时间才弄明白!感谢您提供有关DeepSeq和trace的信息-它们会派上用场的:)