【发布时间】:2014-02-05 19:03:04
【问题描述】:
考虑以下树的定义:
Data Tree a = Empty | Node a (Tree a) (Tree a)
定义函数smallerbigger :: Float -> Tree Float -> ([Float],[Float]),给定一个数字n和一棵树,生成一对列表,其元素小于和大于n。
(问题一开始说树是搜索树,做错了)。
【问题讨论】:
考虑以下树的定义:
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)
对于树,算法的基本形状将保持不变,但最大的区别在于递归方式。您需要递归两个分支,然后一旦从每个分支获得结果,就将它们与当前节点的结果连接在一起。
如果您在为树实现此功能时遇到困难,请随时发表评论,让我知道您遇到了什么问题,并在 gist/pastebin/whatever 中包含指向您的代码的链接。
【讨论】:
Tree 类型以强制执行此属性(正在排序)会很有趣。我想在最简单的情况下,您不会使用 Node 构造函数,而是使用智能构造函数来按预期对参数进行排序?
这里有一些实用程序可以提供简单的解决方案。假设你需要惰性函数。 在这里,您的数据定义仅显示调试能力
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
【讨论】:
感谢所有帮助和建议。
我设法找到了不同的解决方案:
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 )
【讨论】: