我需要一个树实现,我可以访问树中任何节点的父节点。看Data.Tree我看到了树的定义:
data Tree a = Node {
rootLabel :: a, -- ^ label value
subForest :: Forest a -- ^ zero or more child trees
}
因此,如果我有一个树节点Tree a
,我可以访问其标签及其子节点。但是也可以访问其父节点?是否必须根据我的需求选择不同的实施方案?你会推荐哪个套餐?
答案 0 :(得分:8)
如果我没有弄错的话,你要求的基本上是LYAH's section on Zippers中实现的内容。
我不会试图比Miran更好地解释它,但基本的想法是在你穿越树时跟踪你来自哪棵树,以及你正在向下移动的树枝。您没有直接在数据结构中跟踪节点的父节点,但是当您遍历树时,所有信息都可用。
答案 1 :(得分:6)
Data.Tree
故意没有节点引用自己的父母。这样,对父节点(或其他分支中的节点)的更改不需要重新创建整个树,并且内存中的节点可以与多个树共享。像这样的结构这个术语是"持久的"。
您可以实现一个知道自己父节点的节点;结果结构将不会持久化。明确的选择是始终知道树的根节点在哪里;这是任何语言的良好实践。
允许Data.Tree
知道其父母的一个库是rosezipper,documentation can be found here。
答案 2 :(得分:1)
试试这个:
data Tree a = Leaf | Node a (Tree a) (Tree a) (Tree a) deriving (Eq, Show)
您可以将父树保存到第三个(或任何其他)树中。 例如:
singleton::(Ord a)=>a->Tree a
singleton x = Node x Leaf Leaf Leaf
insert::(Ord a)=>a->Tree a->Tree a
insert x Leaf = singleton x
insert x t@(Node a l r p) = insertIt x t p
where insertIt x Leaf (Node a l r p) = Node x Leaf Leaf (Node a Leaf Leaf Leaf)--1*
insertIt x t@(Node a l r p) parent
| x == a = t
| x < a = Node a (insertIt x l t) r p
| x > a = Node a l (insertIt x l t) p
此行中的1 *您可以保存整个父级:
where insertIt x Leaf parent = Node x Leaf Leaf parent