Functional programming 使用OCAML中提供的高阶函数检查树是否为BST
所以,让我先说,这是我过去的作业的一部分,我无法解决,但因为我正在准备一个测试,我想知道如何做到这一点。我有讲师提供的map_tree和fold_tree的以下实现:Functional programming 使用OCAML中提供的高阶函数检查树是否为BST,functional-programming,ocaml,binary-search-tree,higher-order-functions,Functional Programming,Ocaml,Binary Search Tree,Higher Order Functions,所以,让我先说,这是我过去的作业的一部分,我无法解决,但因为我正在准备一个测试,我想知道如何做到这一点。我有讲师提供的map_tree和fold_tree的以下实现: let rec map_tree (f:'a -> 'b) (t:'a tree) : 'b tree = match t with | Leaf x -> Leaf (f x) | Node (x,lt,rt) -> Node (f x,(map_tree f lt),(map_tree f rt)) let
let rec map_tree (f:'a -> 'b) (t:'a tree) : 'b tree =
match t with
| Leaf x -> Leaf (f x)
| Node (x,lt,rt) -> Node (f x,(map_tree f lt),(map_tree f rt))
let fold_tree (f1:'a->'b) (f2:'a->'b->'b->'b) (t:'a tree) : 'b =
let rec aux t =
match t with
| Leaf x -> f1 x
| Node (x,lt,rt) -> f2 x (aux lt) (aux rt)
in aux t
我需要使用上述函数实现一个验证树是否为BST的函数,到目前为止,这就是我所完成的,我得到了错误:
Error: This expression has type bool but an expression was expected of type
'a tree
这是我的代码:
let rec smaller_than t n : bool =
begin match t with
| Leaf x -> true
| Node(x,lt,rt) -> (x<n) && (smaller_than lt x) && (smaller_than rt x)
end
let rec greater_equal_than t n : bool =
begin match t with
| Leaf x -> true
| Node(x,lt,rt) -> (x>=n) && (greater_equal_than lt x) && (greater_equal_than rt x)
end
let check_bst t =
fold_tree (fun x -> true) (fun x lt rt -> ((check_bst lt) && (check_bst rt)&&(smaller_than lt x)&&(greater_equal_than rt x))) t;;
让rec小于tn:bool=
开始比赛
|叶x->true
|节点(x,lt,rt)->(x为真
|节点(x,lt,rt)->(x>=n)&&(大于lt x)&(大于rt x)
结束
让我们检查一下=
折叠树(funx->true)(funx lt rt->((检查lt)和&(检查lt)和&(小于lt x)和&(大于等于rt x))t;;
有什么建议吗?我似乎很难准确理解高阶函数在OCAML中是如何工作的
BST的规范是什么?它是一个二叉树,其中:
- 左子树(也是一个
BST
)中的所有元素都严格小于节点上存储的值
- 右子树中的所有值(也是一个
BST
)都大于或等于节点上存储的值
fold
是一个归纳原则:您必须解释如何处理基本情况(此处为Leaf
情况)以及如何在步骤情况(此处为节点
情况)中组合子情况的结果
Leaf
始终是一个BST
,因此基本情况将非常简单。但是,在节点
情况下,我们需要确保值位于正确的子树中。为了能够执行此检查,我们需要额外的信息。我们的想法是使用折叠
计算:
- 给定的树是否为
BST
- 以及它的所有值存在的时间间隔
让我们引入类型同义词来构建我们的思想:
type is_bst = bool
type 'a interval = 'a * 'a
正如预测的那样,基本情况很简单:
let leaf_bst (a : 'a) : is_bst * 'a interval = (true, (a, a))
在节点
的情况下,我们将值a
存储在节点上,并对左侧(lih
如l
efti
nductionh
ypothesis)和右侧子树递归计算结果。这样构建的树是BST
当且仅当两个子树是(b1和&b2
)及其值与前面描述的属性有关。此新树的值存在的时间间隔现在是更大的(lb1,ub2)
查看折叠树的f1
,f2
函数的类型。调用最后一个函数的方法(在检查中)用f1
中的bool
替换类型'b
,也用f2
替换类型'b
,因此f2
中的两个参数'b
被推断为bool
而不是节点
类似的除外。还可以将rec
添加到函数check\bst>中,因为该函数进行递归调用“非叶”的参数折叠的函数是当前节点的值和折叠子树的结果,而不是子树本身。我无法更改提供的函数。是的,我知道这些值是折叠子树的结果,但如何验证子树是否为BST?我可以获得一个bool来指示它,但我不会是able要验证其他较高的树,并将得到类型不匹配的错误。您需要一个中间步骤,将比bool
更奇特的东西折叠起来,然后从折叠的结果中提取结果。我认为,只有知道子树是否为BST、左子树中的最大值以及sma,才有可能做到这一点L右子树中的最小值。@AndresGalaviz您必须使用折叠树
?算法非常简单,没有折叠谢谢您提供了详细的解释!
let node_bst (a : 'a) (lih : is_bst * 'a interval) (rih : is_bst * 'a interval) =
let (b1, (lb1, ub1)) = lih in
let (b2, (lb2, ub2)) = rih in
(b1 && b2 && ub1 < a && a <= lb2, (lb1, ub2))
let bst (t : 'a tree) : bool =
fst (fold_tree leaf_bst node_bst t)