确定二叉树是否为BST haskell

时间:2018-01-21 08:33:15

标签: haskell binary-tree binary-search-tree

我试图写一个bool函数返回True,如果二叉树是使用递归的bst,我需要一点关于haskell语法的指导。

我理解,对于二进制树是bst,左子树必须始终只包含小于头的节点。并且右子树必须始终只包含大于头部的节点。我正在构建我的函数:

function onVisibilityChange(el, callback) {
    var old_visible;
    return function () {
        var visible = isElementInViewport(el);
        if (visible != old_visible) {
            old_visible = visible;
            if (typeof callback == 'function') {
                callback();
            }
        }
    }
}

var handler = onVisibilityChange(#whatwebelieve, function() {
    $( "#second" ).removeClass( "current-menu-item" )
});


//jQuery
$(window).on('DOMContentLoaded load resize scroll', handler);

但是这段代码会导致错误:

  

无法将预期类型'Bool'与实际类型'Int'匹配

具体参考isBST :: Tree -> Bool --recieve Tree, return bool isBST (Lead i) = True --return true if its only one leaf in tree isBST (Node h l r) = if (((isBST l) < h) && ((isBST r) > h)) then True else False --return true if left subtree < head AND right subtree > head < h部分。我的haskell格式有问题吗?提前致谢

3 个答案:

答案 0 :(得分:3)

  

我的haskell格式化有问题吗?

不,这是一个语义错误。你写道:

(isBST l) < h

所以这意味着你要求Haskell确定l是否是二叉搜索树,TrueFalse,但你无法比较True或{{ 1}}与False。即使你可以(某些语言将h视为True1视为False),但它仍然是不正确的,因为我们想知道是否全部左子树中的节点小于0

所以我们需要以某种方式定义边界。一种方法是通过递归传递参数并执行检查。这样的问题是例如树的根没有边界。我们可以通过使用h是一个边界来解决这个问题:如果它是Maybe Int,边界是“非活动的”可以这么说,如果它是Nothing,则边界是“活动的” “有价值Just b

为了使这项检查更方便,我们可以先写一个检查方法:

b

所以现在我们可以用以下方式进行“三明治检查”:

checkBound :: (a -> a -> Bool) -> Maybe a -> a -> Bool
checkBound _ Nothing _ = True
checkBound f (Just b) x = f b x

因此sandwich :: Ord a => Maybe a -> Maybe a -> a -> Bool sandwich low upp x = checkBound (<) low x && checkBound (>) upp x 给出一个下限和一个上限(两个sandwich s)和一个值,并检查下限和上限。

因此我们可以使用:

编写一个函数Maybe a
isBST'

我们需要考虑两种情况:isBST' :: Maybe Int -> Maybe Int -> Tree -> Bool isBST' low upp ... = .... 案例,其中应满足“三明治约束”,Leaf x案例Node h l r应满足“三明治约束”以及hl应该对不同的约束条件进行平衡。对于r,它就像是:

Leaf x

对于节点案例,我们首先检查相同的约束,然后在isBST' low upp (Leaf x) = sandwich low upp x low之间对左侧部分h强制执行三明治,并在{{1}之间实施三明治}和l表示正确的部分h,所以:

upp

现在我们唯一的问题是使用根元素调用r:这里我们使用isBST' low upp (Node h l r) = sandwich low upp h && isBST' low jh l && isBST' jh upp r where jh = Just h 作为初始边界,所以:

isBST'

当然还有其他方法来强制执行约束,例如传递和更新函数,或者实现检查约束子集的Nothing函数的四种变体。

答案 1 :(得分:1)

我喜欢Willem Van Onsem在他的回答中的教学方法。

我打算删除我的答案,但我会发布一个“更正”,冒险再次出错:

data Tree = Empty | Node Int Tree Tree deriving show

isBST :: Tree -> Bool

isBST Empty = True
isBST (Node h l r) = f (<=h) l && f (>=h) r && isBST l && isBST r
   where
     f _ Empty = True
     f c (Node h l r) = c h && f c l && f c r

请注意,我使用的是维基百科对BST的定义,

  

每个节点中的密钥必须大于或等于存储的任何密钥   在左子树中,小于或等于存储在中的任何键   右子树。

答案 2 :(得分:1)

马丁,我建议你看看威廉的回答。

另外,您还可以使用前一个问题中提到的maxInt函数来定义此函数:

isBST (Node h l r) = ... (maxInt l) ... -- at some point we will need to use this

根据您对BST的定义:

  

我理解,对于二进制树是bst,左子树必须   始终只包含小于头部的节点。和正确的子树   必须始终只包含大于头部的节点。

我还要补充一点,节点的子树也应该是BST。

所以我们可以用以下方法定义这个要求:

isBST (Node h l r) =
  ((maxInt l) < h) -- the left subtree must contain nodes less than the head
  && ((minInt r) > h) -- the right must contain nodes greater than the head
  && (...) -- the left subtree should be a BST
  && (...) -- the right subtree should be a BST

回想一下,您可能需要定义minInt :: Tree -> Int,因为您可能知道如何做到这一点。