检查Haskell中是否从左到右遍历二叉树

时间:2017-11-16 11:31:42

标签: haskell

我有以下树,这就是我如何访问其节点和叶子的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

1 个答案:

答案 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 }