【发布时间】:2019-07-11 07:31:18
【问题描述】:
考虑由以下类型定义的二叉树和一元树,以及将二叉树和一元树转换为列表的函数 flatten(例如,flatten (Node (Leaf 10) 11 (Leaf 20)) 是 [10,11,20]):
data Tree a = Leaf a | Node (Tree a) a (Tree a) | UNode a (Tree a) deriving (Show)
flatten :: Tree a -> [a]
flatten (Leaf x) = [x]
flatten (Node l x r) = flatten l ++ [x] ++ flatten r
flatten (UNode l x) = [l] ++ flatten x
我正在尝试定义一个递归函数reverseflatten,它将列表转换为二叉树和一元树,特别是以以下模式的方式,它适用于长度
reverseflatten :: [a] -> Tree a
reverseflatten [x] = (Leaf x)
reverseflatten [x,y] = UNode x (Leaf y)
reverseflatten [x,y,z] = Node (Leaf x) y (Leaf z)
reverseflatten [x,y,z,x'] = Node (Leaf x) y (UNode z (Leaf x') )
reverseflatten [x,y,z,x',y'] = Node (Leaf x) y ( Node (Leaf x') z (Leaf y'))
reverseflatten [x,y,z,x',y',z'] = Node (Leaf x) y ( Node (Leaf x') z ( UNode y' (Leaf z')))
reverseflatten [x,y,z,x',y',z',x''] = Node (Leaf x) y ( Node (Leaf x') z ( Node (Leaf z') y' (Leaf x'')))
我将如何创建这样一个递归函数,对于任何有限列表,形成上面定义的那种二叉树?下面的答案没有这样做,因为它不遵循上面的模式。
编辑:
我对大于 2 的偶数列表遵循的过程应该是相当透明的(您获取对应于奇数列表的树,然后添加一个一元节点)。
我从奇数列表构造树的一般过程是这样的。 reverse flatten[x,y,z] 是 Node (Leaf x) y (Leaf z)。然后对于下一个奇数列表[x, y, z, x', y'],我想在reverseflatten [x,y,z] 的情况下将z 保留在其先前的位置(其中z 是最后的右下叶),所以位置@ 987654333@ 和Node (Leaf x') z (Leaf y') 一样,排在第二位,所以这种情况下的树就像reverseflatten [x,y,z] 的树一样,只是我们在右下叶z 周围添加了节点。然后我希望 x' 和 y' 围绕 z,按照它们在列表中出现的顺序,因此是 Node (Leaf x') z (Leaf y')。
然后对于下一个奇数列表reverseflatten [x,y,z,x',y',z',x''],我也有类似的想法。我希望 y' 保留在 reverseflatten [x,y,z,x',y'] 和 reverseflatten [x,y,z,x',y',z', x'']) 中的位置,通过 z' 和 x'' 包围 y' 来构建,按照它们在列表中出现的顺序。
【问题讨论】:
-
@Willem Van Onsem:那么它实际上是一棵一元树,由一个母节点和一个子节点组成,它是一个叶子。我将编辑我的问题。
-
我只看了一眼,但我不太确定这里的递归模式是什么。我认为它与
reverseFlatten (x:y:xs) = Node (Leaf x) y (reverseFlatten xs)具有相同的 shape (与上面的单例和 2 元素列表案例一样),但是将列表元素分配给节点或叶子的精确方式似乎很奇怪.你能用语言解释一下思维过程吗? [这样做可能会让你在获得正确的递归定义方面走得很远。] -
@Robin Zigmond:我们从
[x,y,z]形成Node (Leaf x) y (Leaf z),然后从[x,y,z,x']形成Node (Leaf x) y (UNode z (Leaf x') )。然后对于[x, y, z, x', y'] I wanted to preservez`,在reverseflatten [x,y,z]的情况下,将z定位在其先前的位置,然后将z定位在Node (Leaf x') z (Leaf y')中,排在第二位。然后我希望x'和y'成为z的女儿,按照它们在列表中出现的顺序,因此Node (Leaf x') z (Leaf y')。 -
@Robin Zigmond:那么对于
reverseflatten [x,y,z,x',y',z',x''],我也有类似的想法(我希望y'' 仍然是一个母节点(就像reverseflatten [x,y,z,x',y']和reverseflatten [x,y,z,x',y',z']一样) ) , 和女儿z'和x') -
@Robin Zigmond:所以一般的想法是,只要列表是奇数,我们就保留前一个奇数列表的树,但添加两个女儿:一个女儿在左下角树的最后一个最右边的元素对应于前一个奇数列表,另一个子元素在右下角。
标签: haskell recursion tree binary-tree