【发布时间】:2019-07-11 16:26:23
【问题描述】:
考虑以下二叉树和一元树的定义,一个函数 flatten,它将二叉树和一元树转换为列表(例如,flatten (Node (Leaf 10) 11 (Leaf 20)) 是 [10,11,20])和一个函数 reverseflatten,它将列表转换为二叉树(以此处描述的特定方式 (Defining a function from lists to binary and unary trees) 并如下图所示):
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 :: [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)))
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))) 相同?
reverseflatten 构成下图中的一系列树。
例如,reverseflatten [x,y,z] 形成图中的树 2,reverseflatten [x,y,z, x'] 形成树 3,reverseflatten [x,y,z, x', y'] 形成树 4,reverseflatten [x,y,z, x', y', z'] 形成树 5,reverseflatten [x,y,z, x', y', z', x''] 形成树 6,等等。
我想要的是reverseflatten x: xs 与(reverseflatten(flatten(reverseflatten x:xs))) 相同。所以我需要设计flatten所以才有这个效果。
我做了以下尝试(flatten Node l x r 的情况应该分为r 是叶子的情况和不是叶子的情况):
flatten :: Tree a -> [a]
flatten (Leaf x) = [x]
flatten (UNode l x) = [l] ++ flatten x
flatten (Node l x r)
| r == Leaf y = [l, x, r]
| otherwise = flatten (Node l x (revflat2 ([head $ tail r] ++ [head r] ++ tail (tail r)))
但这会产生:
experiment.hs:585:1: error:
parse error (possibly incorrect indentation or mismatched brackets)
|
585 | flatten (UNode l x) = [l] ++ flatten x
| ^
【问题讨论】:
-
首先简化问题 - 真正的问题是
flatten $ reverseflatten [1..5]不等于[1..5],您显然希望它是。 (由于 Haskell 是参照透明的,如果它们相等,将reverseflatten应用于每一边会产生相同的结果。)(我不知道如何解决这个问题,尽管它与你相当复杂和不自然的配方有关“反向展平”,但只是说考虑根本问题而不是其后果会更简单。) -
@Robin Zigmond:我可以(礼貌地)乞求不自然的不同吗?在自然语言语法和语义(我的领域)中,我设计的配方实际上是非常自然的 :) 当然,从其他角度来看它可能是不自然的,也许你来自哪里......
-
公平地说,这是一个见仁见智的问题,我将澄清我的第一条评论以反映这一点。好吧,显然我不能再编辑评论了,但希望这可以澄清一下。无论如何,我真正的意思是,你不能用一个简单的 2/3 行递归定义来表达它,而是最终需要一个辅助函数,两个函数都有 4 种情况。
-
您从上一篇文章的答案中获取了
reverseflatten,这似乎是错误的。这个答案实际上是正确的,还是我们仍然应该以您之前的描述作为参考?目前,您想要的结构只有一个非常非正式的描述,众所周知,这很容易被误解。一些关于它来自哪里、它在你的领域中意味着什么的上下文将有助于澄清这种情况。 -
如果您希望
reverseflatten (flatten (reverseflatten xs)))始终为真,那么您的代码可能基于某些数据结构描述,其中包括此属性持有的证明。你应该逐行检查你的实现,如果它确实符合你的运营商定义的要求。
标签: haskell recursion tree binary-tree