我想计算具有任意分支数的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
现在,我遇到一个错误。如何编写正确的模式来解决此问题?
答案 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) = ...
如果不对参数加上括号,则编译器将无法知道n
和xs
/ []
是属于Node
还是{{1} }。
下一个问题是您的递归调用是在maxBranching
列表上完成的,而不仅仅是Tree Int
。您需要做的是获取每个子树的maxBranching,然后将结果相互比较。因此,第一种简单的方法是:
Tree Int
maxBranching (Node n xs) = max (length xs) (maximum (map maxBranching xs))
将在列表map
的每个元素上运行maxBranching
,并返回xs
的数组。 Int
将占据列表中的最大值。 maximum
和max
之间的区别在于,maximum
仅接受两个参数并将其进行比较,而max
则接受一个任意长的列表。
我们可以通过在创建的列表中添加maximum
并在所有内容上运行max
来摆脱length xs
,例如:
maximum
如果您不知道,maxBranching (Node n xs) = maximum $ (length xs):(map maxBranching xs)
等同于将括号放在行的其余部分(或多或少)。
您还可以将智能方法用作折叠之类的方法,但我只是想让您了解所做的错误以及如何在不更改解决方案核心思想的情况下解决这些错误。