【问题标题】:Check if a binary tree is traversed from left to right in Haskell检查Haskell中是否从左到右遍历二叉树
【发布时间】:2017-11-18 03:33:18
【问题描述】:

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

【问题讨论】:

  • 听起来你只是想检查树是否是 BST。
  • @RoadRunner,不,他没有,因为示例树不是 BST,但通过了。

标签: haskell


【解决方案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 }

【讨论】:

  • 我对这个答案投了反对票,因为您的 Tree 是部分记录,这是个坏建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多