2011-11-29 53 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。將數據結構作爲最後一個參數使得部分應用程序更易於使用,並且使定義更加簡潔。