List 二叉树的最大和最小元素haskell

List 二叉树的最大和最小元素haskell,list,haskell,search,tree,List,Haskell,Search,Tree,考虑以下树的定义: Data Tree a = Empty | Node a (Tree a) (Tree a) 定义函数smallerbigger::Float->Tree Float->([Float],[Float]),该函数给定一个数字n和一棵树,生成一对元素小于或大于n的列表 (问题最初指出树是一个搜索树,这是错误的)。对于列表,您可以实现与以下类似的算法 smallerbigger :: Ord a => a -> [a] -> ([a], [a]) smalle

考虑以下树的定义:

Data Tree a = Empty | Node a (Tree a) (Tree a)
定义函数
smallerbigger::Float->Tree Float->([Float],[Float])
,该函数给定一个数字n和一棵树,生成一对元素小于或大于n的列表


(问题最初指出树是一个搜索树,这是错误的)。

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

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)
smallerbigger::Ord a=>a->[a]->([a],[a])
smallerbigger x xs=go x xs[]
哪里
go y[]lt gt=(lt,gt)
go y(z:zs)lt gt
|z=y=go y zs lt(z:gt)
对于一棵树,算法的基本形状将保持不变,但最大的区别在于递归的方式。您将需要递归两个分支,然后在获得每个分支的结果后,将它们与当前节点的结果连接在一起


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

这里是一组实用程序,可以提供简单的解决方案。假设您需要惰性函数。 在这里,您的数据定义添加了仅显示调试功能

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 
smallerbigger::Ord a=>a->Tree a->([a],[a])
smallerbigger p t=(takeWhile(p)$asList$reverseTree t)
main=let t=fromList[1..10]
在做
打印t
打印$smallerbigger 7吨
但在另一方面,我们可能希望在第二个列表中保持顺序,同时我们确信我们永远不会创建第一个列表。所以我们可以删除和目标分隔符相等的元素,并在其上跨越列表

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

smallerbigger p=span(感谢所有的帮助和建议

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

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 )
smallerbigger::Ord a=>a->Tree a->([a],[a])
smallerbigger n(节点RD)=
设(e1,e2)=smallerbigger n e
(d1,d2)=小比格犬n d
如果r>n,那么(e1++d1,r:(e2++d2))

否则,如果r+1给出了一个很好的提示,但没有实际解决问题,我认为从技术上讲,问题中没有任何东西指定树是排序的(“排序的”?正确的术语是什么?),即左节点比右节点小的假设可能并不总是成立。@FrerichRaabe:“搜索树”通常意味着它已排序。@hammar当然,我只是学究了。:-)事实上,设置一个
类型以强制执行此属性(正在排序)会很有趣。我想在最简单的情况下,您不会使用
节点
构造函数,而是使用一个智能构造函数,按照预期对参数进行排序?很抱歉造成混淆。本练习不假设它是一个搜索树。我编辑了我的问题。谢谢你指出它,请告诉我你的想法或任何更正!你的类型不正确,你的代码不正确,你不应该接受你要求评论和更正的答案(值得投反对票)!