【问题标题】:Biggest and smallest element of a binary tree haskell二叉树haskell的最大和最小元素
【发布时间】:2014-02-05 19:03:04
【问题描述】:

考虑以下树的定义:

Data Tree a = Empty | Node a (Tree a) (Tree a)

定义函数smallerbigger :: Float -> Tree Float -> ([Float],[Float]),给定一个数字n和一棵树,生成一对列表,其元素小于和大于n

(问题一开始说树是搜索树,做错了)。

【问题讨论】:

    标签: list haskell search tree


    【解决方案1】:

    对于列表,您可以实现类似的算法

    smallerbigger :: Ord a => a -> [a] -> ([a], [a])
    smallerbigger x xs = go x xs [] []
        where
            go y [] lt gt = (lt, gt)
            go y (z:zs) lt gt
                | z <  y = go y zs (z:lt) gt
                | z >= y = go y zs lt (z:gt)
    

    对于树,算法的基本形状将保持不变,但最大的区别在于递归方式。您需要递归两个分支,然后一旦从每个分支获得结果,就将它们与当前节点的结果连接在一起。

    如果您在为树实现此功能时遇到困难,请随时发表评论,让我知道您遇到了什么问题,并在 gist/pastebin/whatever 中包含指向您的代码的链接。

    【讨论】:

    • +1 给出一个很好的提示,但没有真正解决问题
    • 我认为从技术上讲,问题中没有任何内容指定树是排序的(“有序”?正确的术语是什么?),即左节点小于右节点的假设可能并不总是成立.
    • @FrerichRaabe:“搜索树”通常意味着它已排序。
    • @hammar 当然,我只是在迂腐。 :-) 事实上,设置Tree 类型以强制执行此属性(正在排序)会很有趣。我想在最简单的情况下,您不会使用 Node 构造函数,而是使用智能构造函数来按预期对参数进行排序?
    • 很抱歉造成混乱。该练习不假设它是一个搜索树。我编辑了我的问题。谢谢指出
    【解决方案2】:

    这里有一些实用程序可以提供简单的解决方案。假设你需要惰性函数。 在这里,您的数据定义仅显示调试能力

    data Tree a = Empty | Node a (Tree a) (Tree a) deriving Show
    

    接下来我们需要一个小工具来轻松创建树。以下代码正在构建一个与原始列表非常相似的非常不平衡的树。

    fromList:: [a] -> Tree a
    fromList [] = Empty
    fromList (x:xs) = Node x Empty (fromList xs)
    

    以列表形式简单而明显地表示树。元素的顺序被保留。

    asList:: Tree a -> [a]
    asList Empty = []
    asList (Node x left right) = asList left ++ x: asList right
    

    接下来我们假设我们需要一对可能是惰性的列表,无论我们的目的地是什么。 我们正在保持使用在中间某处具有无限结构的树的能力,但不是在最后一个或最后一个元素。 这个定义以懒惰的方式沿着相反的方向走我们的树。

    reverseTree:: Tree a -> Tree a
    reverseTree Empty = Empty
    reverseTree (Node x left right) = Node x (reverseTree right) (reverseTree left)
    

    接下来我们最终构建我们的程序。它可以创建比第一个参数更小和更大的两个可能的无限元素列表。

    smallerbigger::Ord a => a-> Tree a -> ([a],[a])
    smallerbigger p t = (takeWhile (<p) $ asList t, takeWhile (>p) $ asList $ reverseTree t)
    
    main = let t = fromList [1..10]
        in do
            print t
            print $ smallerbigger 7 t 
    

    但另一方面,我们可能希望保留第二个列表中的顺序,同时我们确信我们永远不会点击bottom 构建第一个列表。所以我们可以删除等于目标分隔符的元素,并在其上展开列表。

    smallerbigger p = span (<p) . filter(/=p) . asList 
    

    【讨论】:

      【解决方案3】:

      感谢所有帮助和建议。

      我设法找到了不同的解决方案:

      smallerbigger :: Ord a => a -> Tree a -> ([a], [a])
      smallerbigger n (Node r e d) = 
          let (e1,e2) = smallerbigger n e
              (d1,d2) = smallerbigger n d
          in if      r>n then (   e1++d1,  r:(e2++d2)) 
             else if r<n then (r:(e1++d1),    e2++d2 )
             else             (   e1++d1,     e2++d2 )
      

      【讨论】:

      • 请告诉我您的想法或更正!
      • 您的类型不正确,您的代码不正确,并且您不应该接受您要求 cmets 和更正的答案(值得一票否决)!
      猜你喜欢
      • 2021-12-21
      • 2018-06-29
      • 2012-11-28
      • 2022-11-15
      • 2020-11-01
      • 2016-03-18
      • 1970-01-01
      • 2014-03-05
      • 2011-03-08
      相关资源
      最近更新 更多