一般情況:
我想知道如何寫入樹(即更改底層的特定節點,將其替換爲具有舊節點作爲其左側子節點的不同值的節點和一個新的節點作爲右子)
具體的應用程序,計劃使更多的困難:
我試圖把一個遊戲類似於20道題,從文件中讀取現有的樹,詢問用戶的各種問題,如果它不知道答案會詢問用戶在最終猜測和正確答案以及正確答案之間的區別問題,並將新條目添加到遊戲中E(更換位置的猜測與新問題是在指向的猜測,答案節點)在haskell中重寫樹
0
A
回答
4
時常有單子結構,這種樹嫁接之間的緊密對應關係。這裏有一個例子
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Functor
instance Monad Tree where
return = Leaf
Leaf a >>= f = f a
Branch l r >>= f = Branch (l >>= f) (r >>= f)
凡(>>=)
所做的無非就是基於一些功能f :: a -> Tree a
葉延伸(樹嫁接)更多。
然後,我們可以很容易地進行嫁接你正在尋找
graftRight :: Eq a => a -> a -> Tree a -> Tree a
graftRight a new t = t >>= go where
go a' | a' == a = Node a new
| otherwise = Leaf a'
但是,這是低效得不得了,因爲它會在你的樹尋找你想更換一個具體參觀每Leaf
。如果我們知道更多信息,我們可以做得更好。如果樹以某種方式訂購併分類,那麼您可以使用fingertree
或splaytree
進行有效的替換。如果我們知道節點,我們可以使用Zipper來替換它的路徑。
data TreeDir = L | R
data ZTree a = Root
| Step TreeDir (Tree a) (ZTree a)
它可以讓我們一步進出的樹
stepIn :: Tree a -> (Tree a, ZTree a)
stepIn t = (t, Root)
stepOut :: (Tree a, ZTree a) -> Maybe (Tree a)
stepOut (t, Root) = Just t
stepOut _ = Nothing
根的,一旦我們在裏面,走在任何方向上我們喜歡
left :: (Tree a, ZTree a) -> Maybe (Tree a, ZTree a)
left (Leaf a, zip) = Nothing
left (Branch l r, zip) = Just (l, Step R r zip)
right :: (Tree a, ZTree a) -> Maybe (Tree a, ZTree a)
right (Leaf a, zip) = Nothing
right (Branch l r, zip) = Just (r, Step L l zip)
up :: (Tree a, ZTree a) -> Maybe (Tree a, ZTree a)
up (tree, Root) = Nothing
up (tree, Step L l zip) = Just (branch l tree, zip)
up (tree, Step R r zip) = Just (branch tree r, zip)
和編輯葉子
graft :: (a -> Tree a) -> (Tree a, ZTree a) -> Maybe (Tree a, ZTree a)
graft f (Leaf a, zip) = Just (f a, zip)
graft _ _ = Nothing
或者也許所有o f使用我們從上面的綁定在某個位置下的葉子!
graftAll :: (a -> Tree a) -> (Tree a, ZTree a) -> (Tree a, ZTree a)
graftAll f (tree, zip) = (tree >>= f, zip)
,然後我們可以做我們的移植
graftBelow :: (a -> Tree a) -> [TreeDir] -> Tree a -> Maybe (Tree a)
graftBelow f steps t = perform (stepIn t) >>= stepOut where
perform = foldr (>=>) Just (map stepOf steps) -- walk all the way down the path
>=> (Just . graftAll f) -- graft here
>=> foldr (>=>) Just (map (const up) steps) -- walk back up it
stepOf L = left
stepOf R = right
>>> let z = Branch (Branch (Leaf "hello") (Leaf "goodbye"))
(Branch (Branch (Leaf "burrito")
(Leaf "falcon"))
(Branch (Leaf "taco")
(Leaf "pigeon")))
>>> graftBelow Just [] z == z
True
>>> let dup a = Branch (Leaf a) (Leaf a)
>>> graftBelow dup [L, R] z
Just (Branch (Branch (Leaf "hello")
(Branch (Leaf "goodbye")
(Leaf "goodbye")))
(Branch (Branch (Leaf "burrito") (Leaf "falcon"))
(Branch (Leaf "taco") (Leaf "pigeon"))))
>>> graftBelow dup [L, R, R] z
Nothing
之前走在樹中的任意點一般有很多的方式來實現這一目標。
+0
謝謝!這比我寫作的方式更有效率(它會搜索每一片葉子,而不是記錄所採取的步驟) – gallabytes
相關問題
- 1. 樹木在Haskell
- 2. 在haskell中標記樹
- 3. 樹重寫與[]
- 4. 重寫樹
- 5. 應用性重寫(Haskell)
- 6. Haskell佈局樹
- 7. 返回無限樹在Haskell
- 8. 最大樹深度在Haskell
- 9. 哈夫曼樹在Haskell
- 10. 無價值樹一 - 在Haskell
- 11. 在Haskell中編寫Zipwith
- 12. 如何在Haskell中操縱樹木
- 13. 2-3-4樹haskell
- 14. 平衡AVL樹haskell
- 15. 樹與Haskell遍歷
- 16. 如何寫在Haskell
- 17. Antrl3條件樹重寫
- 18. Antlr樹重寫規則
- 19. ANTLR表達式重寫中間樹
- 20. Haskell重寫規則和函數組合
- 21. Haskell重寫規則不在不同的模塊中觸發
- 22. 計算Haskell中樹中的元素
- 23. Haskell中的'重複'?
- 24. Haskell - 樹的預訂編號
- 25. Haskell - 二進制搜索樹
- 26. 找到深度的樹haskell
- 27. Haskell:將樹變成地圖
- 28. haskell檢查平衡樹
- 29. Haskell N-ary樹構建
- 30. haskell二叉樹函數
到目前爲止您有任何嘗試嗎?你的樹結構是什麼樣的? – bheklilr
是啊,(我現在的工作,只是可怕的低效率) 替換功能我結束了使用將貫穿整棵樹,尋找節點與給定的輸入值,那麼它將與另一個樹結構中替換這些節點 的樹看起來像這樣:數據樹a =空|節點a(Tree a)(Tree a)派生(Show,Read,Eq) – gallabytes