【问题标题】:How to move a subtree between trees in Haskell?如何在 Haskell 中的树之间移动子树?
【发布时间】:2014-09-03 14:01:36
【问题描述】:

对于两个多路树,t1 和 t2,使用定义

type Forest a = [Tree a]
data Tree a   = Node {
        rootLabel :: a,     
        subForest :: Forest a
    }

如何编写一个函数,从 t1 中删除子树并将其插入到 t2 中的给定节点?

我想签名看起来像

moveSubTree :: ((Tree x a) x (Tree x a)) -> (Tree x Tree)

即它需要一棵树和定义要删除的子树的父节点,以及定义插入原始子树的点的第二棵树和节点。

如果需要,可以组合删除然后添加子树的单独函数。

【问题讨论】:

  • 什么是x?此外,Haskell 没有指针。树值只是一棵树,而不是任何事物的子树。您需要提供一些方法来从树中获取子树,例如路径(索引列表)。
  • 您必须比“...在 t2 中的给定深度插入它”更具体——在任何给定深度的树中可能有多个点,您想要哪个把它移到哪里?
  • 这是有道理的——我应该把“插入到 t2 中的给定节点”。我会更新问题以反映这一点。

标签: function haskell recursion types functional-programming


【解决方案1】:

您可以在树中的“路径”处进行编辑和读取。

data Dir    = L | R
type Path   = [Dir]
data Tree a = Leaf | Node a (Tree a) (Tree a)

read :: Path -> Tree a -> Maybe (Tree a)
read []     t = t
read (s:ss) t = case t of
  Leaf       -> Nothing
  Node a l r -> case s of
    L -> read ss l
    R -> read ss r

edit :: Path -> (Tree a -> Tree a) -> Tree a -> Maybe (Tree a)
edit []     f t = Just (f t)
edit (s:ss) f t = case t of
  Leaf       -> Nothing
  Node a l r -> case s of
    L -> do
      l' <- edit ss f l
      return (Node a l' r)
    R -> do
      r' <- edit ss f r
      return (Node a l r')

然后使用此工具,您可以将子树从一条路径“复制并粘贴”到另一条路径

cnp :: Path -> Path -> Tree a -> Maybe (Tree a)
cnp readPath writePath t = do
  subtree <- read readPath t
  edit writePath (const subtree) t

有趣的是,“路径上的子树”形成了一个Lens,它包含了这两个操作之间的共同结构。

【讨论】:

  • 一个小问题,TS 想要一个多路树,而不是二叉树。
  • 是的。这个想法通过使用type Path = [Int] 推广到多路树,并注意到路径可能会因为太长和引用不存在的子树而“错过”。
猜你喜欢
  • 2019-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2020-02-07
  • 1970-01-01
  • 2017-06-22
  • 2013-12-17
相关资源
最近更新 更多