我试图写一个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格式有问题吗?提前致谢
答案 0 :(得分:3)
我的haskell格式化有问题吗?
不,这是一个语义错误。你写道:
(isBST l) < h
所以这意味着你要求Haskell确定l
是否是二叉搜索树,True
或False
,但你无法比较True
或{{ 1}}与False
。即使你可以(某些语言将h
视为True
而1
视为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
应满足“三明治约束”以及h
和l
应该对不同的约束条件进行平衡。对于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
,因为您可能知道如何做到这一点。