遍历具有任意数量分支的树

时间:2018-11-16 15:47:53

标签: haskell

我想计算具有任意分支数的Tree中的最大度数。

data Tree a = Node a [Tree a]
  deriving (Eq, Show)

{-

       2
    /  |  \
   7   3   1
       |  / \
       0 3   2
 For this case: Answer will be 3. 
-}
tree1 :: Tree Int
tree1 = Node 2 [Node 7 [], Node 3 [Node 0 []], Node 1 [Node 3 [], Node 2 []]]

--I am doing something like this:

maxBranching :: Tree Int -> Int
maxBranching Node n [] = 1
maxBranching Node n xs = max (length xs) maxBranching xs

现在,我遇到一个错误。如何编写正确的模式来解决此问题?

3 个答案:

答案 0 :(得分:3)

首先,maxBranching的参数类型为Tree Int而不是[Tree Int],并且您想将所有子节点映射到最大程度,因此应该为:

map maxBranching xs

不是

maxBranching xs

第二,参数需要放在括号中,否则,函数maxBranching会接受3个参数。

将它们全都设为:

maxBranching :: Tree Int -> Int
maxBranching (Node _ []) = 1
maxBranching (Node _ xs) =  maximum $ (length xs) : (map maxBranching xs)

答案 1 :(得分:3)

您要遍历一棵生成某种“汇总值”的树。这是同构折叠的经典示例。树木的一般折叠如下:

foldTree :: (a -> [b] -> b) -> Tree a -> b
foldTree f (Node a bs) = f a (map (foldTree f) bs)

这里的想法是在每个树节点上

Node r [t1,t2,t3]

我们首先将每个子代递归地减少为一个汇总值,然后应用给定的函数和根值以及子代的汇总来生成树的汇总。

现在

maxBranching :: Tree a -> Int
maxBranching = foldTree $
  \_ bs -> maximum (length bs : bs)

也就是说,在每个节点上,我们采用该节点及其每个子节点的最大分支数。

答案 2 :(得分:0)

首先,您需要在参数周围加上括号,如下所示:

maxBranching (Node n xs) = ...

如果不对参数加上括号,则编译器将无法知道nxs / []是属于Node还是{{1} }。

下一个问题是您的递归调用是在maxBranching列表上完成的,而不仅仅是Tree Int。您需要做的是获取每个子树的maxBranching,然后将结果相互比较。因此,第一种简单的方法是:

Tree Int

maxBranching (Node n xs) = max (length xs) (maximum (map maxBranching xs)) 将在列表map的每个元素上运行maxBranching,并返回xs的数组。 Int将占据列表中的最大值。 maximummax之间的区别在于,maximum仅接受两个参数并将其进行比较,而max则接受一个任意长的列表。

我们可以通过在创建的列表中添加maximum并在所有内容上运行max来摆脱length xs,例如:

maximum

如果您不知道,maxBranching (Node n xs) = maximum $ (length xs):(map maxBranching xs) 等同于将括号放在行的其余部分(或多或少)。

您还可以将智能方法用作折叠之类的方法,但我只是想让您了解所做的错误以及如何在不更改解决方案核心思想的情况下解决这些错误。