在Haskell中找到给定树的最大分支

时间:2019-03-04 17:50:12

标签: haskell tree

我是Haskell的初学者。在这里,我试图理解一个Haskell函数,该函数计算树的最大分支度。

以下是数据类型:

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

leaf :: a -> Tree a
leaf a = Node a []

这里是实现:

maxBranching :: Tree a -> Int
maxBranching (Node _ ts) = let localBranching = length ts in
                             max localBranching (maxBranchingOfSubtrees ts)

  where maxBranchingOfSubtrees :: [Tree a] -> Int
        maxBranchingOfSubtrees [] = 0
        maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)

这是示例输入:

Node 2 [leaf 7, Node 3 [leaf 0], Node 1 [leaf 3, leaf 2]]

我不明白这个表达:

maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)

max是如何将第一个元素与列表的其余部分进行比较的?每次迭代后,它在哪里更新最大值?如果我看到何时将列表的第一个元素设为Leaf 7作为maxBranching x传递,则没有这种情况,它如何返回列表的第一个元素的长度,然后如何{ {1}}处理列表的其余部分?而起初maxBranchingOfSubtress包含列表localBranching?任何形式的详细帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您问题的简单答案是,所有类型都完美地结合在一起。

如果为(x:xs) :: [Tree a],则为x :: Tree axs :: [Tree a],因为(:) :: a -> [a] -> [a]或此处为(:) :: Tree a -> [Tree a] -> [Tree a]

(:) :: Tree a ->       [Tree a]         ->   [Tree a]
(       x         :       xs       )    ::   [Tree a]
----------------------------------
        x :: Tree a       xs :: [Tree a]

根据函数的签名

 maxBranching    :: Tree a -> Int
              x  :: Tree a
---------------------------------
(maxBranching x) ::           Int

 maxBranchingOfSubtrees     :: [Tree a] -> Int
                        xs  :: [Tree a]
---------------------------------------------
(maxBranchingOfSubtrees xs) ::             Int

所以我们确实可以拥有

max :: Int        -> Int                         -> Int
max (maxBranching x) (maxBranchingOfSubtrees xs) :: Int

因此max不是 “将第一个元素与列表的其余部分进行比较”。而是将第一个元素上的计算maxBranching 的结果与列表其余部分上的计算maxBranchingOfSubtrees 的结果进行比较。

最后一点,您问如何知道如何做到这一点?只需使用相同的maxBranchingOfSubtrees配方即可。换句话说,通过做同样的事情 -但这一次的事情比以前更“小”。列表的尾部是列表的 part

因此最终,此递归将会顺利进行,我们将得到答案-如果树的列表不是无限的,那就是。因此,这假设分支因子不是无限的。

因此,这将找到节点子树的最大分支因子,然后将其与该节点的分支因子进行比较,以产生总体最大值。


另一种看法是

    maxBranchingOfSubtrees [] = 0
    maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)
                                  = (max . maxBranching) x (maxBranchingOfSubtrees xs)

适合foldr模式,

    maxBranchingOfSubtrees = foldr (max . maxBranching) 0

这符合映射模式

    maxBranchingOfSubtrees = foldr max 0 . map maxBranching

并且有一个内置函数,

    maxBranchingOfSubtrees = maximum . (0 :) . map maxBranching

然后将其替换为主要功能

maxBranching :: Tree a -> Int
maxBranching (Node _ ts) = max (length ts) (maxBranchingOfSubtrees ts)
                         = max (length ts) (maximum (0 : map maxBranching ts))
                         = maximum (length ts : map maxBranching ts)

使用高阶函数表示相同的算法,而不是手动递归循环