data Tree a = Leaf | Node (Tree a) a (Tree a) deriving (Eq, Show)
unfoldTree:: (b -> Maybe (b, a, b)) -> b -> Tree a
unfoldTree f b =
case f b of
Nothing -> Leaf
Just (lt, x, rt) -> Node (unfoldTree f lt) x (unfoldTree f rt)
鉴于上面的两条信息,我被要求实现树构建功能。
我的尝试是
treeBuild :: Integer -> Tree Integer
treeBuild 0 = Leaf
treeBuild n = treeUnfold (\b -> if b < 2^n-1
then Just(2*b, b + 1, 2*b + 1)
else Nothing)
0
基本案例在n = 0的情况下工作正常,但我知道函数完全错误。有人可以向我重新解释一下3-tuple Just
将如何运作?在正常展开中,Just
中的第一个元素将是我想要的元素,第二个元素将用于继续展开,但这是如何在3元组中工作的?
作为示例输出:
treeBuild 2 ----> Node (Node Leaf 0 Leaf) 1 (Node Leaf 2 Leaf)
编辑:
我不完全确定Just如何在这里工作,对于Just(2*b, b + 1, 2*b + 1)
的情况,其中b从0开始,它是否变为Just(0, 1, 0)
?我如何实际增加b?
答案 0 :(得分:5)
我认为在粘贴unfoldTree
的定义时省略了空格。应该是这个吗?
unfoldTree f b = case f b of ...
Maybe (b, a, b)
没有任何内在意义,但在这种特殊情况下,您可以看到unfoldTree
将元组中的项绑定到lt
,x
和{{} 1}}。中间值rt
用于创建节点,x
和lt
用于为rt
的递归调用设定种子。
要解释您的示例输出,请注意unfoldTree
始终绑定到n
。 2
的初始0
参数表示treeUnfold
函数首先检查(\b -> ...)
,然后生成0 < 2^n-1
。
中间值Just (2*0, 0+1, 2*0+1)
是树中根节点的值。左侧子树的构建方式类似,但0+1
现在为b
,右侧子树使用2*0
构建为b
。
你提到这是家庭作业,它应该用2*0+1
个节点构建一个树。我将猜测2^n - 1
值不计算,并且您希望以广度优先顺序对这些节点进行编号,并希望此示例可以将您带到附近。以下是如何做到这一点:
treeBuild :: Int -> Tree Int treeBuild n = treeUnfold (\b -> if b < 2^n - 1 then Just (2*b+1, b, 2*b+2) else Nothing) 0
我到达此处的方法是绘制深度为3的二叉树。我将节点编号为根Leaf
,左节点编号为0
,右节点编号为{{ 1}}。底部节点从左到右编号,从1
开始,到2
结束。
现在模式可见:如果当前节点编号为4
,则其左右节点分别编号为7
和b
。由于2*b+1
是深度为2*b+2
的树中的节点总数,并且我按广度优先顺序对节点进行编号,因此当2^n - 1
确保我停止时返回n
将树填充到深度Nothing
。