【问题标题】:Defining a function from lists to binary and unary trees定义从列表到二叉树和一元树的函数
【发布时间】: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 preserve z`,在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


【解决方案1】:

我尝试更改代码以捕获您要求的模式。我的实现效率不是很高,但目前想不出。 我希望我正确理解了这个模式。

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:xs) = revflat2 (x:y:xs)

revflat2 :: [a] -> Tree a
revflat2 [x] = (Leaf x)
revflat2 [x,y] = UNode y (Leaf x)
revflat2 [x,y,z] = Node (Leaf x) y (Leaf z)
revflat2 (x:y:xs) = Node (Leaf x) y (revflat2 ([head $ tail xs] ++ [head xs] ++ tail (tail xs)))

【讨论】:

  • @Koralp Catalsakal:这并不能完全生成我想要的模式(请参阅我对 Robin Zigmond 的评论)
  • @Robin Zigmond:是的,我希望它和我的示例一样。那么我该如何修改以上内容来解决这个问题呢?例如,我想要一个列表[1..5]Node (Leaf 1) 2 (Node (Leaf 4) 3 (Leaf 5))[1..7]Node (Leaf 1) 2 (Node (Leaf 4) 3 (Node (Leaf 6) 5 (Leaf 7)))
  • @Robin Zigmond:在上面写了回复:)
  • @Koralp Catalsakal:另外,目前reverseflatten [1..5]Node (Leaf 1) 2 (Node (Leaf 4) 3 (Leaf 5),但(reverseflatten(flatten(reverseflatten [1..5]))) 不会返回reverseflatten [1..5],这是最理想的。如何修改flatten 使reverseflatten x: xs(reverseflatten(flatten(reverseflatten x:xs)))
  • @user65526 在reverseflatten 中,我们切换数组的顺序。例如,对于 [1,2,3,4,5] 的输入,我们的reverseflatten 给出了 [1,2,4,3,5] 的输出。但是,flatten 函数没有捕捉到这一点,并假定数组的顺序是树的顺序。因此,为了能够正确使用flatten,您需要反转reverseflatten 中的切换操作。我目前无法处理它,但如果我有时间会尝试:)
猜你喜欢
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多