我试图获取一个函数来计算从根到具有偶数节点的叶子的所有路径(计算根和叶子) 我的树看起来像这样:
data Tree = Leaf Int | Node Int Tree Tree
到目前为止,我得到的是一个计算树中所有节点的函数,这很容易:
countNodes (Leaf _) = 1
countNodes (Node _ x y) = 1+ countNodes x + countNodes y
现在我看到一堆关于树木的问题,但我觉得没有任何答案对我有所帮助,所以我只是要问自己。当到达叶子时,如何使功能的一部分停止?我知道这与我的问题有关,可以用递归来思考。
我尝试做的是从根目录中列出所有路径,但我总是得到一个函数,它可以获取树中的所有元素并以某种方式将它们组合在一起。 我错过了一些简单的事情,请帮忙。 (或链接我一个完全符合我要求的答案)
答案 0 :(得分:3)
我认为最简单的方法是创建一个可以描述树中路径的数据类型:
data Path = L Path | R Path | End deriving (Eq, Show)
这种类型基本上是一个列表,但有两个前置构造函数告诉你左转或右转。这样可以方便地按路径查找项目,或者您可以编写一个函数,为您提供树中所有路径的列表。
-- Note that this can fail: lookupNode (Leaf 1) (L End) == Nothing
lookupNode :: Tree -> Path -> Maybe Tree
allPaths :: Tree -> [Path]
如果您可以编写allPaths
函数,那么您可以在其上编写所需的函数。首先,列出基本案例:
allPaths (Leaf _) = [End]
allPaths (Node _ left right) = _
要填补漏洞_
,请考虑列出从Node
开始并递归left
的所有路径的含义。你需要在所有这些路径的开头有一个L
,所以你可以把以下内容放在那里
allPaths (Node _ left right) = (map L $ allPaths left)
同样,您需要处理right
树:
allPaths (Node _ left right) =
(map L $ allPaths left) ++
(map R $ allPaths right)
现在:
> let tree =
Node 1
(Node 2 -- L _
(Leaf 3) -- L (L End)
(Node 4 -- L (R _)
(Leaf 5) -- L (R (L End))
(Leaf 6) -- L (R (R End))
)
)
(Leaf 7) -- R End
> allPaths tree
[L (L End),L (R (L End)), L (R (R End)),R End]
现在,要找到上面有偶数个节点的Leaf
,首先编写一个计算路径长度的函数:
pathLength :: Path -> Int
pathLength End = 0
pathLength (L rest) = 1 + pathlength rest
pathLength (R rest) = 1 + pathLength rest
evenNodeCountPaths :: Tree -> [Path]
evenNodeCountPaths tree = filter (even . pathLength) $ allPaths tree
注意:可以使用
执行此操作data Dir = L | R | End
type Path = [Dir]
但是这会导致像[End,End,L,R,End]这样的无效路径,这听起来没有任何意义。出于这个原因,我选择了类似列表的data Path
。您必须编写自己的pathLength
函数,但此公式使得无法使用无效路径。
答案 1 :(得分:1)
可能更容易计算偶数和奇数路径的数量。
evenAndOdd (Leaf _) = (0, 1)
evenAndOdd (Node _ l r) = let
(el, ol) = evenAndOdd l
(er, or) = evenAndOdd r
in (ol+or, el+er)
如果你真的必须,你可以根据这个来定义一个函数来计算偶数路径。
evenOnly = fst . evenAndOdd