【问题标题】:Maximum tree depth in HaskellHaskell 中的最大树深度
【发布时间】:2014-02-09 22:25:00
【问题描述】:

给我这个类型定义:

data Tree = Leaf Char | Branch2 Char Tree Tree | Branch3 Char Tree Tree Tree

我如何编写一个方法来给出树的最大路径长度(计算路径中的节点)?

【问题讨论】:

  • 今后,请展示您为解决遇到的问题所做的任何尝试。 Stackoverflow 是一个在特定问题上获得帮助的地方,而不是让别人为你编写代码的地方。
  • 这种树型可以容纳2个元素吗?我们可以从三元素树中删除一个元素吗?我们要么必须在那里添加Branch1 Char Tree,要么毕竟只有Empty

标签: haskell recursion tree


【解决方案1】:

我可能会通过使用延续传递来编写尾递归解决方案。

depth :: Tree -> Int
depth t = go t id
 where
  go (Leaf _)          k = k 0
  go (Branch2 _ l r)   k = go l $ \dl -> go r $ \dr -> k (1 + max dl dr)
  go (Branch3 _ l m r) k = go l $ \dl -> go m $ \dm -> go r $ \dr -> k (1 + max dl (max dm dr))

【讨论】:

  • 我相信它有效,但我从未见过这样的东西^^。你能解释一下吗?
  • @Chryb 查看here 的解释。
【解决方案2】:

lazy corecursive breadth-first tree traversal:

treedepth tree = fst $ last queue
  where
    queue = (1,tree) : gen 1 queue

    gen  0   p                        = []
    gen len ((d,Leaf    _      ) : p) = gen (len - 1) p 
    gen len ((d,Branch2 _ l   r) : p) = (d+1,l) : (d+1,r) : gen (len + 1) p 
    gen len ((d,Branch3 _ l c r) : p) = (d+1,l) : (d+1,c) : (d+1,r) : gen (len + ??) p 

将其更改为深度优先遍历会将其变为常规递归。

【讨论】:

  • @ChrisTaylor 要么是这个,要么是递归的深度优先代码,depending on tree shape,如果它是事先知道的。 :)
【解决方案3】:
depth :: Tree -> Int
depth (Leaf _) = 1
depth (Branch2 c left right) = max((depth(left) + 1) (depth(right) + 1))
depth (Branch3 c left center right) = max(max((depth(left) + 1) (depth(right) + 1)) (depth(center) + 1))

对吗?对不起,我在递归编程方面不太擅长。

【讨论】:

  • 此代码无法编译。语法max((depth(left) + 1) (depth(right) + 1)) 不正确。推荐的样式是仅在将要作为另一个函数的单个参数的子表达式分组时使用括号,并在括号冗余时避免使用括号。您可以改为将其写为max (depth left + 1) (depth right + 1)
  • max (max a b) cmaximum [a,b,c] 相同。
【解决方案4】:

您可能需要编写一个递归函数来执行此操作。对于每个 Tree 构造函数,您需要在函数中使用不同的大小写。首先,你知道任何Leaf 的深度都是1,所以

maxDepth :: Tree -> Int
maxDepth (Leaf _) = 1
maxDepth (Branch2 c left right) = maximum [???]
maxDepth (Branch3 c left center right) = maximum [???]

我会让你完成剩下的功能。您也可以使用几种不同的方式(例如使用max 而不是maximum)。

【讨论】:

  • 通常,叶子的深度是0,而不是1
  • @kosmikus 在这种情况下,叶子包含数据。树的此定义不包括空分支。如果我计算存储在这棵树中的Chars 的数量,我会说Leaf 中有一个,所以我认为它应该是我定义的方式。
  • 我看不出数据的存在或计算字符数的愿望与它有什么关系。节点的深度通常是到根的最小路径长度。如果树是单叶,那么叶就是根,路径的长度为0
  • @kosmikus 然后我们讨论两种不同的测量。我会说Leaf 'a' 的高度为 1,Branch2 'a' (Leaf 'b') (Leaf 'c') has height 2. If Tree` 有一个 Empty 构造函数,我会说Empty 的高度为 0。相反,您正在测量根元素的高度之间的差异(始终为 1 ) 和最高分支的高度,所以我们总是不同意 1。
  • @kosmikus 根节点的深度为 0,但包含一个根节点(无论是叶还是分支)的路径长度为 1。Empty 树不包含节点,因此其深度是 0。但是是否将叶子算作节点可能是一个见仁见智的问题——我们主要处理树的分支方面,还是处理数据承载方面。 IE。我们区分 btwn 空树和 1 元素树吗? -- 顺便说一句,这个数据类型定义是有缺陷的,它不能表示其中有 2 个数据元素的树(也不能表示 0)。 Empty 构造函数也应该存在(然后Leaf 变得多余)。
猜你喜欢
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2016-01-24
  • 2016-08-26
  • 2015-01-22
  • 1970-01-01
  • 2015-02-12
  • 2016-10-18
相关资源
最近更新 更多