【发布时间】:2019-12-25 00:32:13
【问题描述】:
所以,这棵树不是二叉搜索树。它没有特定的顺序,只是为了快速访问特定索引(第n个元素),而不是一个元素是否存在。
树的形式是这样的:
data Tree a = Leaf a | Node Int (Tree a) (Tree a) deriving Show
对于这棵特定的树,Node 构造函数中的“Int”是该节点下的元素数(或叶子数)。
使用这种结构,我复制了我在网上找到的讲座中可用的部分树函数(我在尝试理解时稍作修改):
buildTree :: [a] -> Tree a
buildTree = growLevel . map Leaf
where
growLevel [node] = node
growLevel l = growLevel $ inner l
inner [] = []
inner (e1:e2:rest) = e1 <> e2 : inner rest
inner xs = xs
join l@(Leaf _) r@(Leaf _) = Node 2 l r
join l@(Node ct _ _) r@(Leaf _) = Node (ct+1) l r
join l@(Leaf _) r@(Node ct _ _) = Node (ct+1) l r
join l@(Node ctl _ _) r@(Node ctr _ _) = Node (ctl+ctr) l r
我还能够创建一些用于在树中移动的基本功能。我做了一个找到第 n 个元素并返回它的方法。我还创建了一个 Path 数据类型并实现了一个函数来将路径(在左侧和右侧)返回到特定索引,以及一个可以通过路径并返回该节点/叶子的函数。
现在,我想做的是删除功能。这里的问题在于树是“多叶的”,或者至少这是给我带来困难的原因。
如果我在删除路径中最终得到一个 Leaf,则没有“Null”或等效项可以替换它。此外,如果我尝试停在最后一条路径(如 [L]),并检查那是否是节点,那么如果它是叶子,则将整个节点替换为对面等,我遇到了改变的问题整个树以反映该更改,而不仅仅是返回删除的结尾,并更改树中的所有数字以反映叶子的更改。
我希望在删除项目时保留订单,就像您要使用列表作为更简单的示例:
del 4 [1, 2, 3, 4, 5, 6, 7] = [1, 2, 3, 4, 6, 7]
如果有更简单的方法来构建树(仍然可以包含重复元素并保持顺序),那是什么?
有没有办法使用这种方法删除元素?
【问题讨论】:
-
旁注:将
join/(<>)写成l <> r = Node (count l + count r) l r,提取count :: Tree a -> Int作为自己的函数不是更好吗?我想你也想给Node添加一个爆炸:Node !Int (Tree a) (Tree a)。 -
@HTNW 如果我实现了一个计数功能,那么每次更改某些内容时对整个节点的计数不会违背树速度的目的吗?另外,我不太了解 bang 模式,但据我了解,这似乎是个好主意。
-
如
count (Leaf _) = 1; count (Node n _ _) = n。count使树的要点更加清晰:Tree是正常的二叉树,除了count函数比正常更有效。 -
empty = Node 0 empty empty.
标签: haskell recursion binary-tree