Haskell二叉树

时间:2012-11-05 22:08:19

标签: haskell tree binary-tree

我有一份作业:

1)为树定义一个数据结构TTT,其中每个顶点有0个,1个或2个子节点,每个树叶(带有0个子节点的顶点及其自身)包含一个自然数列表;

2)创建一个函数mm,它有两个参数 - 基于函数f(Integer->Integer)TTT的树x。结果它应该为TTT使用函数x为列表中的每个元素(引用1)定义提供基于f的树;

功能f可以有以下表示形式(abc):

a :: Integer -> Integer
a x = x * x

b :: Integer -> Integer
b x = x `mod` 9

c :: Integer -> Integer
c x = x * x * x

有人可以帮我吗?

2 个答案:

答案 0 :(得分:18)

重要建议

通过Learn You a Haskell for Great Good真的值得一试。这是一个很好的教程。

实践!玩!通过更改简介来扩展此分配。你能用Strings而不是Integers吗?你能用三个子树做一棵树吗?你能做一个分支机构也有数据吗?你能创建一个采用任何数据类型的树吗?了解Functor s。他们为什么好?你能创建一个代表计算的树,用+等操作的分支和数字离开吗?

你玩的越多,你就越自信。成为课堂上的人,在它出现之前发现了什么。每个人都会向你寻求帮助,当你被要求解决你小组中任何人遇到的棘手问题时,你会学到更多。

问题1:树数据类型

以下是一些提示。

这个二叉树有两个子树或一个布尔叶:

data BTree = Leaf Bool | Branch BTree BTree 
  deriving (Eq,Show)

此数据结构有三个项目,包括Bool s:

列表
data Triple = Triple Int String [Bool]
  deriving (Eq,Show)

这个有三种不同的可能性,因为Expr出现在右侧,它有点像树。

data Expr = Var Char | Lam Char Expr | Let Char Expr Expr
  deriving (Eq,Show)

现在你需要一个有三种可能性的方法,其中leaf有一个Integers列表,另外两个有一个子树或两个子树。将这些想法放在一起。

问题2:在树上映射函数

我们称之为apply-a-function-anywhere-you-can-map“ping”函数。 map为列表执行此操作,fmap为其他内容执行此操作。

让我们定义一个函数,它接受Bool -> Bool并将其映射到第一个例子:

mapBTree :: (Bool -> Bool) -> BTree -> BTree
mapBTree f (Leaf b) = Leaf (f b)
mapBTree f (Branch b1 b2) = Branch (mapBTree f b1) (mapBTree f b2)

和另一个映射三联的人。这次我们必须让它适用于列表中的每个Bool

mapBoolTriple :: (Bool -> Bool) -> Triple -> Triple
mapBoolTriple f (Triple i xs bs) = Triple i xs (map f bs)

注意我使用了标准函数map,其功能如下:

map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs

所以它从我的列表中的每个f开始应用x,从前面开始。

我是如何做这种事的

但这不是我真正做到这一点的方式。我要添加

{-# LANGUAGE DeriveFunctor #-}

在我的文件的顶部,这将让我写

data BinTree a = ALeaf a | ABranch (BinTree a) (BinTree a)
   deriving (Eq, Show, Functor)

然后我可以做

fmap (*100) (ABranch (ALeaf 12) (ALeaf 34))

哪会给我

ABranch (ALeaf 1200) (ALeaf 3400)

fmap更灵活:我也可以

fmap (<20) (ABranch (ALeaf 12) (ALeaf 34))
  -- ABranch (ALeaf True) (ALeaf False)

fmap show (ABranch (ALeaf 12) (ALeaf 34))
 -- ABranch (ALeaf "12") (ALeaf "34")

没有我写一行函数fmap。我认为这会给你10/10使用其他语言功能,但0/10解决问题设置,所以不要那样做,但要记住并尽可能使用它。

更多建议

有乐趣学习Haskell。它有时令人兴奋,但它会极大地奖励你学习。你将能够用更传统的语言在Haskell中编写一些程序的十分之一的程序。多想想!写得少!

答案 1 :(得分:0)

当它按预期工作时,我已经达到了这个目的,除了我没有Ingeter列表,而是在叶子中有一个Integer。我现在的问题是我应该在这段代码中改变什么,以便叶子只能包含整数列表?到目前为止,我尝试修改树定义,如下所示:

data TTT a = ALeaf [Integer] | ABranch (TTT a) (TTT a)

并修改数据:

testTree1 = ABranch (ALeaf [1,2,3]) (ALeaf [4,5,6])

但在这种情况下,整数列表保持未修改。

下面是稳定代码,其中有一个Integer in leaf。

{-# LANGUAGE DeriveFunctor #-}

data TTT a = ALeaf a | ABranch (TTT a) (TTT a)
   deriving (Eq, Show, Functor)

-- Function "mm"
mm f t = let
   in fmap (f) t

-- Function "tt_a"
tt_a = mm a testTree1

-- Function "tt_b"
tt_b = mm b testTree1

-- Function "tt_c"
tt_c = mm c testTree1

-- Function "a"
a :: Integer -> Integer
a x = x * x

-- Function "b"
b :: Integer -> Integer
b x = x `mod` 9

-- Function "c"
c :: Integer -> Integer
c x = x * x * x

-- TTT type tree`s for tests
testTree1 = ABranch (ALeaf 1) (ALeaf 2)
testTree2 = ABranch (ALeaf 11) (ALeaf 12)