首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在列表中每层打印二叉树

在列表中每层打印二叉树
EN

Stack Overflow用户
提问于 2010-11-01 12:05:03
回答 4查看 2K关注 0票数 0

函数应该在层中打印参数树的标记,作为层列表。每个层中的节点和叶标记是从左到右列出的,即层中最左边的节点,列表的第一个元素,最右边的节点是列表的最后一个元素。Ord类型的参数指示从最小层到最大层(TopDown)的升序层还是从最大层到最小层(BottomUp)的降序层。

代码语言:javascript
复制
data Tree = Leaf Integer | Node Integer Tree Tree

type Layer = [Integer]

data Ord = BottomUp | TopDown

wLayer :: Tree -> Ord -> [Layer] 

示例1:我们使用参数调用函数wLayer

wLayer (节点1(节点2(叶21) (叶22)) (节点3(叶31) (叶32)) TopDown结果:[1,2,3,21,22,31,32]

例2: wLayer (节点1(节点2(叶21) (叶22)) (节点3(叶31) (叶32)) BottomUp结果:[21,22,31,32,2,3,1]

我怎样才能实现这一目标?

编辑

代码语言:javascript
复制
data Tree = Leaf Integer
          | Node Integer Tree Tree
type Layer = [Integer]
data Ord   = BottomUp | TopDown

writeLayer :: Tree -> Ord -> [Layer]
writeLayer Leaf x = [x]
writeLayer (Node x lt rt) BottomUp = (writeLayer rt BottomUp) ++ [x] ++ (writeLayer lt BottomUp)
writeLayer (Node x lt rt) TopDown  = [x] ++ (writeLayer lt TopDown) ++ (writeLayer rt TopDown)

这是我的程序,但它不工作,我怎么能修复它呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-11-02 05:18:09

这里有一个简单的方法来实现这一点。它接受一个级别上的所有节点,并从它们中提取整数值,然后对这些相同节点的所有子节点进行递归。之后,您将在Ord上进行匹配,以确定是否需要反转列表。

代码语言:javascript
复制
writeLayer t o =
    case o of
        BottomUp -> reverse $ makeLayer [t]
        TopDown -> makeLayer [t]
    where
        extract (Node i _ _) = i
        extract (Leaf i) = i
        children (Node _ a b) = [a, b]
        children _ = []
        makeLayer [] = []
        makeLayer ts = map extract ts : (makeLayer $ concat $ map children ts)
票数 2
EN

Stack Overflow用户

发布于 2010-11-01 12:58:18

一些提示:

  • Tree是一个Leaf的情况很简单。
  • BottomUpTopDown的区别似乎在于您是否反转了Layer的列表
  • Tree是一个Node时,您将不得不在子树上递归并以某种方式组合结果

编辑: OK,让我们集中讨论其中的第一个。

你对于这个案子的方程式是

代码语言:javascript
复制
writeLayer Leaf x = [x]

首先,Leaf x需要放在括号中,因为它是一个Tree值。

代码语言:javascript
复制
writeLayer (Leaf x) = [x]

第二,方程需要反映writeLayer有两个参数(正如上面所写的,它只需要一个参数)。对于Leaf值,我们不关心返回结果的顺序--我们给出的答案是相同的--但是我们仍然必须接受参数。我们使用_来表示我们不关心参数之上的问题,也不打算使用它。

代码语言:javascript
复制
writeLayer (Leaf x) _ = [x]

第三,[x]Integers的(单元素)列表--但是我们应该返回一个Layers的列表,我相信您可以找到解决这个问题的方法。

最后,注意电脑给你的错误信息。理解他们。

票数 2
EN

Stack Overflow用户

发布于 2010-11-11 11:36:34

Paul的回答给出了水平顺序遍历的共同递归定义--对列表的展开。(练习:使用makeLayer编写Data.List.unfoldr。)这也是我最喜欢的方式,参见被低估的人

但它也可以递归地进行--就像树上的折叠一样。这些定义与清单上的foldr相似,定义如下:

代码语言:javascript
复制
foldt :: (Integer->a) -> (Integer->a->a->a) -> Tree -> a
foldt f g (Leaf n)     = f n
foldt f g (Node n t u) = g n (foldt f g t) (foldt f g u)

然后,通过一个简单的树折叠给出水平级遍历,并使用一个可能的reverse

代码语言:javascript
复制
wLayer :: Tree -> Order -> [Layer] 
wLayer t o = (if o==BottomUp then reverse else id) (foldt single glue t)

我冒昧地将您的标志类型Order重命名为无效名称冲突,并使其成为Eq的实例。

代码语言:javascript
复制
data Order = BottomUp | TopDown deriving Eq

函数single对叶子进行水平顺序遍历:

代码语言:javascript
复制
single :: Integer -> [Layer]
single n = [[n]]

glue将一个标签和两个子节点的遍历组合到一个节点的遍历中:

代码语言:javascript
复制
glue :: Integer -> [Layer] -> [Layer] -> [Layer]
glue n x y = [n] : longzipwith (++) x y

关键成分是函数longzipwith,它类似于zipWith,只不过(i)结果的长度是较长的参数的长度,而不是较短的参数,因此(ii)二进制运算符必须是a->a->a

代码语言:javascript
复制
longzipwith :: (a->a->a) -> [a] -> [a] -> [a]
longzipwith f (a:x) (b:y) = f a b : longzipwith f x y
longzipwith f x     []    = x
longzipwith f []    y     = y
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4068681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档