【问题标题】:Finding max branching in a given tree in Haskell在 Haskell 中查找给定树中的最大分支
【发布时间】:2019-03-05 05:52:42
【问题描述】:

我是 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 传递,则没有这种情况,它如何返回列表的第一个元素的长度,然后maxBranchingOfSubtress 如何处理列表的其余部分?然而,起初localBranching 包含列表length = 4?任何形式的详细帮助将不胜感激。

【问题讨论】:

  • 什么 leaf?它不是Tree 定义的一部分;我认为它是一个辅助函数,例如 leaf x = Node x []?
  • FWIW,我将此函数拼写为maxBranching (Node _ ts) = maximum (length ts:map maxBranching ts)
  • 是的,你猜对了。它被定义为一个智能构造器leaf :: a -> Tree a Leaf x = Node x []
  • @Sniper 请在问题部分包含问题详细信息,而不是评论部分。

标签: haskell tree


【解决方案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 配方。换句话说,通过做同样的事情——但这次做的事情比以前“更小”了。列表的尾部是列表的部分

所以最终这个递归会运行它,我们会得到我们的答案——如果树的列表不是无限的,那就是。所以这假设分支因子不是无限的。

所以这会找到一个节点的子树的最大分支因子,然后将它与该节点的分支因子进行比较,以产生整体的最大值。


另一种观点是

    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)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 2011-02-16
    • 2023-04-10
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多