删除Haskell中树中的所有叶子

时间:2017-05-23 15:39:02

标签: haskell tree

嘿伙计们我有问题。我想删除一棵树的所有叶子。 我的树的初始值是data NBaum a = NBlatt a | NKnoten a [NBaum a]。我不知道我怎么能这样做,这是Nblatt空的命令。也许你们可以帮助我。

我的函数应该将NBaum作为输入,输出也是NBaum。entferneBlaetter :: NBaum a -> NBaum a

我已经尝试过这段代码,但这是错误的:

entferneBlaetter (NBlatt _) = NBlatt "test"
entferneBlaetter (NKnoten a b) = NKnoten a (entferneBlaetter_help b)

3 个答案:

答案 0 :(得分:0)

这是一个提示。

在处理NKnoten a b时,我们希望:

  • 扫描b列表中的所有树:
    • 如果我们找到一棵叶子树,我们会从列表中删除它
    • 如果我们找到一个节点树,我们递归地从该节点的子树中删除叶子,并将结果保留在列表中。

基本方法可能是递归编写entferneBlaetter_help

顺便说一句,我认为最好使用entferneBlaetter :: NBaum a -> Maybe (NBaum a)实现此练习。

答案 1 :(得分:0)

一些暗示,如果你已经走到这一步,道歉:

因为在Haskell中,你的树是不可变的,所以从中删除一些东西意味着在没有它的情况下构造一棵新树。因此类型为entferneBlaetter :: NBaum a -> NBaum a

如果允许,您的所有叶子似乎都是NBlatt a个节点,或者可能是NKnoten a []个节点。但请注意,一旦你下降到NKnoten节点,就太晚了;如果没有一棵树,你就无法回归建造一座树。

但是您始终首先扫描父分支,并且叶节点的父节点始终为NKnoten。因此,您可以尝试filter子节点列表。但是,这可能会为您留下一个裸分支NKnoten a []。因此,如果您允许更改entferneBlaetter的类型签名,则可以将Maybe NBaum传递给调用者,然后可以检查所有子节点是否已评估为Nothing,然后传回修剪后的分支或将NKnoten a []替换为NBlatt a

作为奖励,如果您的树由单个叶节点组成,则您可以将其修剪为Nothing。但是,如果您的界面已修复,您仍然可以定义辅助函数entferneBlaetter' :: NBaum -> Maybe NBaum

或者,您可以制作第二个转换过程,用NKnoten a []替换NBlatt a的所有实例。

答案 2 :(得分:0)

问题不是100%根据叶子的构成指定的,以及当树只有一个节点时会发生什么。但是,如果我们想出“叶子”的定义......

isLeaf :: NBaum a -> Bool
isLeaf (NBlatt _)     = True
isLeaf (NKnoten _ []) = True
isLeaf _              = False

...我们可以给出一个递归解决方案,对列表中不是叶子的每个节点进行递归,或者删除它,如果它是。

entferneBlaetter :: NBaum a -> NBaum a
entferneBlaetter (NKnoten s xs) = NKnoten s [entferneBlaetter x | x <- xs, not $ isLeaf x]
entferneBlaetter x              = x