【问题标题】:Testing if binary tree is balanced in Haskell在 Haskell 中测试二叉树是否平衡
【发布时间】:2011-02-21 04:12:11
【问题描述】:

除了递归调用左右子树上的 size 函数之外,还有什么方法可以测试二叉树是否平衡。 abs(size left - size right)

【问题讨论】:

  • 你的二叉树是如何表示的?

标签: function haskell tree binary-tree


【解决方案1】:

所以递归很容易,不是吗?

import Data.Maybe (isJust)

getBalancedSize :: (Monad m, Num b, Ord b) => BinaryTree a -> m b
getBalancedSize Empty = return 0
getBalancedSize (Node _ l r) = do
    sizeL <- getBalancedSize l
    sizeR <- getBalancedSize r
    if abs (sizeL - sizeR) <= 1
        then return $ sizeL + sizeR + 1
        else fail "tree is not balanced"

isBalanced :: BinaryTree a -> Bool
isBalanced = isJust . getBalancedSize

现在假设你有

fold :: (a -> b -> b -> b) -> b -> Tree a -> b
fold _ b Empty = b
fold f b (Node a l r) = f a (fold f b l) (fold f b r)

有一种明显的方法可以将getBalancedSize 重构为对fold 的一次调用。

getBalancedSize = fold f (return 0) where
    f _ l r = do
        sizeL <- getBalancedSize l
        sizeR <- getBalancedSize r
        if abs (sizeL - sizeR) <= 1
            then return $ sizeL + sizeR + 1
            else fail "tree is not balanced"

但你确实需要一些递归函数来遍历递归树结构。

【讨论】:

    【解决方案2】:

    这取决于您的二叉树在 Haskell 中的表示方式。如果是递归数据结构,递归是你唯一的武器……

    【讨论】:

    • 这就是它的定义方式:data BinaryTree a = Empty |节点 a (BinaryTree a) (BinaryTree a)
    • 在这种情况下,除了递归之外,没有其他方法可以沿着树向下下降。
    • 好的,谢谢。我正在尽一切努力解决这个问题,但我无法得到任何完全正确的东西。我认为还有另一种方法,因为这是我的作业问题。我使用递归找到了正确的答案,但可以使用任何其他方法满足平衡二叉搜索树的要求。
    【解决方案3】:

    您可以使用有保证的类型Red-Black Tree。不需要检查它是否平衡,因为类型可以保证它。

    isBalanced = const True
    

    【讨论】:

    • 在类型中编码红黑不变量然后实际使用树是可能的,但一点也不容易。如果您想获得所有类型,那么使用 2-3 树、2-3-4 树或 AVL 树肯定会更好。代码很多,但结构更统一。
    • 红黑并不太复杂。在我对github.com/yairchu/red-black-tree 的尝试中,生成的红黑代码比 AVL 短。
    • 嗯。我很惊讶。我记得,我在红黑上看到的论文在很大程度上影响了效率。
    • @dfeuer:尚未针对效率进行基准测试。可能还有其他更高效的树,我不知道..
    【解决方案4】:

    您可以定义一个新的二叉树来存储它的深度。深度在插入和移除时更新,您可以通过查看存储的深度值来判断它是否平衡。

    根据更新树的频率进行递归计算是一种更好的解决方案。反正比较干净。

    【讨论】:

      【解决方案5】:

      有效确定一棵树是否平衡而不注意其大小的要点是,一旦您知道正确的分支比正确的分支更深一层以上左分支,它到底有多深并不重要。 2级更深? 3? 100?我们不在乎,只发现结果就扔掉可能被认为是低效的。

      isBalanced :: BinaryTree a -> Bool
      isBalanced = and . treeToBalanceSize
      
      treeToBalanceSize :: BinaryTree a -> BalanceSize
      treeToBalanceSize Empty      = []
      treeToBalanceSize (Node l r) = True : mergeBalanceSizes (treeToBalanceSize l) (treeToBalanceSize r)
      
      mergeBalanceSizes :: BalanceSize -> BalanceSize -> BalanceSize
      mergeBalanceSizes []       []       = []
      mergeBalanceSizes [x]      []       = [x]
      mergeBalanceSizes []       [y]      = [y]
      mergeBalanceSizes (x : xs) (y : ys) = (x && y) : mergeBalanceSizes xs ys
      mergeBalanceSizes _        _        = [False]
      
      type BalanceSize = [Bool]
      

      让自己满意

      1. 如果tree 是平衡的并且大小为size,则treeToBalanceSize tree = replicate size True
      2. 如果tree 不平衡,则treeToBalanceSize tree 将以False 结尾。
      3. 评估mergeBalanceSizes [True] list 不会导致评估list 超出其第三个元素。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多