我有以下树,这就是我如何访问其节点和叶子的Int值。我想要做的是编写一个函数“areValuesIncreasing”来检查当树从左到右遍历时节点/叶子的值是否增加。任何帮助将不胜感激。
4 4
/ \ / \
2 3 3 2
/ \ / \ / \ / \
1 3 4 5 - True 1 3 5 4 - False
data Tree = Node Tree Int Tree | Leaf Int deriving Show
treeToInt (Node _ n _) = n
treeToInt (Leaf n ) = n
areValuesIncreasing:: Tree -> Bool
答案 0 :(得分:-1)
我强烈建议将Tree
更改为
data Tree a = Node (Tree a) a (Tree a)
| Leaf a
deriving (...)
并将在我的回答中使用此功能,但将其转换为Tree
就像在任何地方设置a ~ Int
并将Tree Int
替换为Tree
一样简单。
为每个图层创建元素列表,然后检查所有这些元素是否已排序。假设你有一个功能
foldTree :: (a -> b) -> -- Leaf case
(b -> a -> b -> b) -> -- Node case
Tree a -> b
叶子产生一个包含单个列表后跟repeat []
的列表,因为叶子是一个级别上的单个元素,后跟无限多个空级别
leafCase x = [x] : repeat []
内部节点连接子树'表'成对的子列表,同时也将它们的元素放在顶部的单个列表中:
nodeCase l x r = [x] : zipWith (++) l r
将此折叠在Tree
以获得级别列表,并在最后一个非空的之后将其删除:
levels = takeWhile (not . null) . foldTree leafCase nodeCase
检查每个级别是否已排序:
sorted = all (uncurry (<=)) . (zip <*> tail)
将它们全部混合成一个功能
sortedTree = all sorted . takeWhile (not . null) . levels
where sorted = all (uncurry (<=)) . (zip <*> tail)
levels = foldTree (\l -> [l] : repeat []) (\l x r -> [x] : zipWith (++) l r)
与recursion-schemes
相同:
makeBaseFunctor ''Tree
-- data TreeF a b = NodeF b a b | LeafF a
-- ...
levelsSorted :: (Recursive t, Foldable (Base t), Ord a) => (Base t [[a]] -> a) -> t -> Bool
levelsSorted get = all sorted . takeWhile (not . null) . levels
where sorted = all (uncurry (<=)) . (zip <*> tail)
levels = cata $ \x -> [get x] : foldr (zipWith (++)) (repeat []) x
levelsSortedTree :: Ord a => Tree a -> Bool
levelsSortedTree = levelsSorted $ \case { LeafF _ x _ -> x; NodeF x -> x }