Haskell 定义从列表到二元树和一元树的函数
考虑由以下类型定义的二元树和一元树,以及一个函数Haskell 定义从列表到二元树和一元树的函数,haskell,recursion,tree,binary-tree,Haskell,Recursion,Tree,Binary Tree,考虑由以下类型定义的二元树和一元树,以及一个函数flatte,该函数将二元树和一元树转换为列表(例如,flatte(节点(叶10)11(叶20))是[10,11,20]): 我试图定义一个递归函数,reverseflatten,它将列表转换为二元树和一元树,具体方式如下,适用于长度为2的列表,应该是相当透明的(取对应于奇数列表的树,然后添加一元节点)。 我从奇数列表构造树的一般过程如下反向展平[x,y,z]是节点(叶x)y(叶z)。然后对于下一个奇数列表,[x,y,z,x',y'],我想将z保留
flatte
,该函数将二元树和一元树转换为列表(例如,flatte(节点(叶10)11(叶20))
是[10,11,20]
):
我试图定义一个递归函数,reverseflatten
,它将列表转换为二元树和一元树,具体方式如下,适用于长度为2的列表,应该是相当透明的(取对应于奇数列表的树,然后添加一元节点)。
我从奇数列表构造树的一般过程如下<代码>反向展平[x,y,z]是节点(叶x)y(叶z)
。然后对于下一个奇数列表,[x,y,z,x',y']
,我想将z
保留在它以前的位置,比如reverseflatten[x,y,z]
(其中z
是最后一个右下叶),然后将z
放置在第二位,如节点(叶x')z(叶y')
,因此,这种情况下的树与reverseflatten[x,y,z]
的树类似,只是我们在右下叶z
周围添加了节点。然后,我希望x'和y'围绕z
,按照它们在列表中出现的顺序排列,从而形成节点(叶x')z(叶y')。
然后,对于下一个奇数列表
reverseflatten[x,y,z,x',y',z',x']
,我有一个类似的想法。我希望y'
在reverseflatten[x,y,z,x',y']
和reverseflatten[x,y,z,x',y',z']
中保留它的位置,并按照它们在列表中出现的顺序围绕y'
来构建它。我试图更改代码以捕获您要求的模式。我的执行效率不是很高,但目前想不出有什么效果。
我希望我正确地理解了这个模式
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 :: [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)))
@Willem Van Onsem:那么它实际上是一棵一元树,由一个母节点和一个单独的子节点组成,子节点是一片叶子。我将编辑我的问题。我只是简单地看了一下,但我不太确定这里的递归模式是什么。它的形状与
reverseFlatten(x:y:xs)=Node(Leaf x)y(reverseFlatten xs)
的形状相同(单元素和两元素列表的情况与上面的情况完全相同),但是列表元素分配给节点或叶子的精确方式似乎很奇怪。你能用语言解释思维过程吗?[这样做可能会让您在获得正确的递归定义方面走很长的路。]@Robin Zigmond:我们从[x,y,z]
形成节点(叶x)y(叶z)
,然后从[x,y,z,x']
形成节点(叶x)y(叶x')
。然后对于[x,y,z,x',y'],我想在反转平面[x,y,z]
的情况下将z'保留在其先前的位置,并将z
定位在第二位,如节点(叶x')z(叶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'
)@罗宾·齐格蒙德:所以一般的想法是,每当列表是奇数时,我们都会像上次奇数列表一样保留树,但会添加两个子元素:一个子元素位于与上次奇数列表相对应的树的最后一个最右元素的左下角,另一个子元素位于右下角。@Willem Van Onsem:n它实际上是一棵一元树,由一个母节点和一个子节点组成,这是一片叶子。我将编辑我的问题。我只是简单看了一下,但我不太确定这里的递归模式是什么。它的形状与reverseFlatten(x:y:xs)=node(leaf x)y(reverseFlatten xs)
我认为是相同的(单元素和双元素列表的情况与上面的情况完全相同),但是列表元素分配给节点或叶子的精确方式似乎很奇怪。你能用文字解释一下思考过程吗?[这样做可能会让你在获得正确的递归定义方面走很长的路。]@Robin Zigmond:我们形成节点(叶子x)y(叶z)
来自[x,y,z]
,然后节点(叶x)y(叶x'))
来自[x,y,z,x']
。然后对于[x,y,z,x',y'],我想将z`保留在它以前的位置,以防反转latten[x,y,z'
,然后将z
放置在节点(叶x')中
,排在第二位。然后我想x'
和y'
按照它们在列表中出现的顺序成为z
的女儿,因此Node(Leaf x')z(Leaf y')
@Robin Zigmond:然后对于reverseflatten[x,y,z',y',z',x']
我有一个类似的想法(我希望y'
'保持一个母节点(就像reverseflatten[x,y,z,x',y']
和reverseflatten[x,y,z,z',]
一样),有子节点z'
和x'
)@Robin Zigmond:所以,一般的想法是,每当列表是奇数时,我们都会像前一个奇数列表一样保留树,但会添加两个子元素:一个子元素位于与前一个奇数对应的树的最后一个最右元素的左下角
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)))