2011-11-29 50 views
3

我有一个函数,可以按给定顺序(中缀,前缀,后缀和反转中缀,前缀,后缀)将二叉树缩减为节点值列表。下面的代码工作,但我不知道是否有办法做到这一点不只是一个顺序不同的参数重复函数实现6倍:我该如何避免重复类似的表情?

data DOrd = Infix | Praefix | Postfix | GInfix | GPraefix | GPostfix 
data BTree = Nil | BNode Int BTree BTree deriving (Eq,Ord,Show) 

flatten :: BTree -> DOrd -> [Int] 
flatten Nil    _  = [] 
flatten (BNode n b1 b2) Infix = flatten b1 Infix ++ [n] ++ flatten b2 Infix 
flatten (BNode n b1 b2) Praefix = [n] ++ flatten b1 Praefix ++ flatten b2 Praefix 
---6 times basically the same for all the elements in DOrd 

我想过函或基本上延伸深海资源开发有限公司枚举到更复杂的结构 - 但我不知道如何。

+1

TU Vienna? ;-)昨天自己做了。 – firefrorefiddle

+0

@Mike:是的:)我今天也问了导师,他也不知道更好的解决方案。 – mort

回答

6

我不知道G版本的用途。但是,这将工作分解出三个共性我的理解:

data DOrd = Infix | Praefix | Postfix | GInfix | GPraefix | GPostfix 
data BTree = Nil | BNode Int BTree BTree deriving (Eq,Ord,Show) 

flatten :: BTree -> DOrd -> [Int] 
flatten Nil _ = [] 
flatten (BNode n b1 b2) ord = case ord of 
    Praefix -> C++ l ++ r 
    Infix -> l ++ C++ r 
    Postfix -> l ++ r ++ c 
    ... 
    where 
    l = flatten b1 ord -- left 
    r = flatten b2 ord -- right 
    c = [n]   -- current 

这简直是保理的代码是相同的部件在所有情况下为短名称不混淆逻辑根据DOrd值而变化的部分。

+0

GInfix只是Infix颠倒= r-> c-> l – mort

+0

@mort这个命名来自哪里?这不是我熟悉的惯例。 – Carl

+0

来自作业。它只是在玩耍; 'G'代表德国的“Gespielte Variante”,意思是“一个变体只是为了玩耍” – mort

4

将重新排序分成它自己的功能。

flatten :: BTree -> DOrd -> [Int] 
flatten Nil _ = [] 
flatten (BNode n b1 b2) order = reorder order (flatten b1 order) [n] (flatten b2 order) 

reorder :: Monoid m => DOrd -> m -> m -> m -> m 
reorder Infix a b c = mconcat [a, b, c] 
reorder Praefix a b c = mconcat [b, a, c] 
reorder Postfix a b c = mconcat [a, c, b] 
reorder GInfix a b c = mconcat [c, b, a] 
reorder GPraefix a b c = mconcat [c, a, b] 
reorder GPostfix a b c = mconcat [b, c, a] 

您的原始代码只需要它为列表工作,但这将适用于所有monoids。

5

我觉得定义数据结构的折叠功能。将分离出递归在结构的关注这里是有用的,它很可能是可重复使用的其他地方在你的代码:

fold :: (Int -> a -> a -> a) -> a -> BTree -> a 
fold _ x Nil = x 
fold f x (BNode n b1 b2) = f n (fold f x b1) (fold f x b2) 

现在,你可以很容易地写在foldreorder方面flatten(由dave4420的回答启发):

flatten :: DOrd -> BTree -> [Int] 
flatten order = fold f [] 
    where f n b1 b2 = mconcat $ reorder order [n] b1 b2 

reorder Praefix a b c = [a, b, c] 
reorder Infix a b c = [b, a, c] 
... 

注意,我冒昧改变参数的顺序来flatten。将数据结构作为最后一个参数使得部分应用程序更易于使用,并且使定义更加简洁。