Haskell中的树构建功能(家庭作业)

时间:2013-03-21 01:58:57

标签: haskell tree functional-programming

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?

1 个答案:

答案 0 :(得分:5)

我认为在粘贴unfoldTree的定义时省略了空格。应该是这个吗?

unfoldTree f b =
    case f b of ...

Maybe (b, a, b)没有任何内在意义,但在这种特殊情况下,您可以看到unfoldTree将元组中的项绑定到ltx和{{} 1}}。中间值rt用于创建节点,xlt用于为rt的递归调用设定种子。

要解释您的示例输出,请注意unfoldTree始终绑定到n2的初始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,则其左右节点分别编号为7b。由于2*b+1是深度为2*b+2的树中的节点总数,并且我按广度优先顺序对节点进行编号,因此当2^n - 1确保我停止时返回n将树填充到深度Nothing