从树中的根查找偶数路径的数量

时间:2017-01-10 16:05:27

标签: haskell binary-tree

我试图获取一个函数来计算从根到具有偶数节点的叶子的所有路径(计算根和叶子) 我的树看起来像这样:

data Tree = Leaf Int | Node Int Tree Tree
到目前为止,我得到的是一个计算树中所有节点的函数,这很容易:

countNodes (Leaf _) = 1
countNodes (Node _ x y) = 1+ countNodes x + countNodes y

现在我看到一堆关于树木的问题,但我觉得没有任何答案对我有所帮助,所以我只是要问自己。当到达叶子时,如何使功能的一部分停止?我知道这与我的问题有关,可以用递归来思考。

我尝试做的是从根目录中列出所有路径,但我总是得到一个函数,它可以获取树中的所有元素并以某种方式将它们组合在一起。 我错过了一些简单的事情,请帮忙。 (或链接我一个完全符合我要求的答案)

2 个答案:

答案 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