Haskell 总结了通过树的所有路径

Posted

技术标签:

【中文标题】Haskell 总结了通过树的所有路径【英文标题】:Haskell summarize all paths through a tree 【发布时间】:2013-07-04 10:09:44 【问题描述】:

我尝试通过一棵树来总结所有路径,该树从根到最低的子级将每个级别扩展 1 到 10 倍。 我的函数递归地遍历所有子节点,但是我遇到的问题是,当我尝试创建节点列表并在列表中执行此列表时,我变成了列表中的列表...列表中的列表。 我认为我的问题是组合步骤我试图制作一种模式匹配方法,但是当它成为列表列表时应该比较列表并且应该制作新列表并比较它们的方法,如果它只是一种方式(遇到一个列表使用节点而不是使用列表的列表)不起作用。

【问题讨论】:

您的(非工作)代码可能会使您尝试的内容更加清晰:-) 【参考方案1】:

一棵树可以表示为一个 list-monadic-list(一个列表,其中有多个选项用于在每个点恢复它的方式)。那么,你想要的只是这个单子列表上的一个折叠。

import Control.Monad.Trans.List.Funcs (repeatM) -- cabal install List
import qualified Data.List.Class as L

exampleTree = L.take 3 (repeatM [0, 1])

查看所有路径:

ghci> L.toList exampleTree 
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]

总结所有路径:

ghci> L.foldlL (+) 0 exampleTree 
[0,1,1,2,1,2,2,3]

Wrt 这种树的表示形式,ListTree 包为表示为 ListT []s 的树上的树操作(例如 DFS/BFS 迭代)提供了组合器。

【讨论】:

【参考方案2】:
summarize :: Tree a -> [[a]]
summarize Leaf = [[]]
summarize (Node a t1 t2) = do
    t <- [t1, t2]
    map (a:) (summarize t)

编辑:请注意,以上假设Tree 的定义如下:

data Tree a = Leaf | Node a (Tree a) (Tree a)

编辑#2:这个版本的代码可能更清晰:

summarize :: Tree a -> [[a]]
summarize Leaf = [[]]
summarize (Node a t1 t2) = do
    t       <- [t1, t2]
    summary <- summarize t
    return (a:summary)

这个版本有一个很好的特性,它可以写成一个列表推导式:

summarize (Node a t1 t2) = [a:summary | t <- [t1, t2], summary <- summarize t]

【讨论】:

@rightfold 不过,这并不等同。您的版本将最终结果包装在 return 中。 @GabrielGonzalez 哎呀,脑残。下次要多加注意。 :) @rightfold 没关系。第一次写答案时,我犯了完全相同的错误。 :)

以上是关于Haskell 总结了通过树的所有路径的主要内容,如果未能解决你的问题,请参考以下文章

Haskell - 树的fmap和foldMap

haskell中树的最大元素?

Haskell 剖析子图挖掘算法

Haskell,树中的列表列表

如何在 Haskell 中实现 B+ 树?

Haskell 2-3-4 树