【问题标题】:How should I define a binary tree in Haskell?我应该如何在 Haskell 中定义二叉树?
【发布时间】:2015-06-03 02:32:45
【问题描述】:

在 Haskell 中,可以通过以下两种方式之一定义二叉树:

data Tree a = Empty | Branch a (Tree a) (Tree a)

或

data Tree a = Leaf a | Branch (Tree a) (Tree a)

选择其中一个有什么好处?在哪些情况下,一种树结构比另一种更适合?

【问题讨论】:

  • data Tree a = Leaf a | Branch (Tree a) a (Tree a) 应该也能正常工作吧?

标签: algorithm haskell data-structures tree


【解决方案1】:

我认为后者几乎没有用,因为它可以展平为(非空)列表,唯一的区别是分支结构。然而,在运行时仍然难以分析,因为内部节点没有携带额外的信息;当你看到一个分支时,你不能说它的两个子树中的任何一个。要区分它们,您必须遍历它们并从本质上消除我们更喜欢树的 O(log n) 复杂度。

如果有人发现这种数据结构的用例,请告诉我。

【讨论】:

    【解决方案2】:

    正如@PetrPudlák 所说,这取决于。前者更适合搜索树。但是,后一个版本是(免费的)monad,它也很有用:

    instance Monad Tree where
        return = Leaf
        Leaf x >>= f = f x
        Branch t1 t2 >>= f = Branch (t1 >>= f) (t2 >>= f)
    

    (>>=) 运算符对应于“叶替换”。

    Functor 和 Applicative 实例也很有用。 随着 GHC 7.10 的推出,当您定义 Monad 时,它们已成为强制性的。我们可以使用 monad 函数来定义它们:

    instance Functor Tree where fmap = Control.Monad.liftM
    instance Applicative Tree where pure = return; (<*>) = Control.Monad.ap
    

    【讨论】:

      【解决方案3】:

      这在很大程度上取决于您的应用程序。如果树的形状是由元素决定的,前一个定义会更好,例如如果你有一个平衡的二叉树:

      另一方面,如果您的树充当不受约束的元素的容器,而树的形状不依赖于它们,那么将值放在叶子上会更有意义。

      This post Heinrich Apfelmus 很好地展示了这种方法。他定义了

      data Tree v a = Leaf   v a
                    | Branch v (Tree v a) (Tree v a)
      

      所以a类型的值只是在叶子上,但是所有节点(内部和叶子)都用v类型注释,并且只需为v选择各种monoids,我们就会得到不同的有趣数据结构。

      【讨论】:

        【解决方案4】:

        前者肯定更好,因为它可以表示任意二叉树,而后者则不然。比如第二个版本不能代表:

        1. 一棵空树。

        2. 一棵树,它的节点有一个左孩子但没有右孩子(反之亦然)。

        【讨论】:

        • 我可以理解一种类型可以被视为“绝对更好”,因为它允许表示更多情况,但更灵活并不总是等同于“更好”。我的意思是——通过同样的论点,人们可以说玫瑰树比二叉树更好,因为它们可以代表更多的树。
        • @chi 二叉树在问题中明确提及(如果没有明确提及,那将是另一个问题)。二叉树是一个定义明确的概念,后一个版本不允许表示它们。
        • 并非在所有情况下都更好。一些数据结构被实现为仅在叶子中有数据的树。例如,第二个版本可以更好地表示 Huffman 代码树。此外,您提到的两种情况都可以使用Tree (Maybe a) 用第二棵树表示(最终与第一个树同构)。
        • 糟糕,实际上这不会是同构的。不过,我坚持我的另一点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-20
        • 1970-01-01
        • 1970-01-01
        • 2018-09-15
        相关资源
        最近更新 更多