我正在尝试在SML中找到BST中节点的父节点和祖父节点。
我试图修改此功能:
fun search(tree : bst, compare, (data) =
let fun s(Leaf) = NONE
| s(Node{data=nodedata,left=left,right=right}) =
(case compare(data,nodedata) of
LESS => s(left)
| GREATER => s(right)
| EQUAL => SOME (Node{data=nodedata,left=left,right=right}))
in
s(tree)
end
通过改变输入,比较和输出的格式:
fun search(tree : bst, compare, (data) =
let fun s(Leaf) = NONE
|s(Node{data=nodedata,left=Node{data=nodedata1,left=left1,right=right1},right=right}) =
(case compare(data,nodedata) of
LESS => s(left)
| GREATER => s(right)
| EQUAL => SOME nodedata)
显然它不起作用,我想有一种更简单的方法可以做到这一点。
我添加了一个新变量,以便保存我正在检查的每个节点的当前父节点,并且它可以工作,但是(对我来说)很难找到一种方法来保持我检查的节点的祖父。
有什么想法吗?提前谢谢。
答案 0 :(得分:1)
首先,你的搜索功能无法正常工作,所以我把它清理了一下。为了避免类型声明错误中的未绑定类型变量,您必须将bst
类型定义为'a bst
。我还修复了一个paranthesis错误。这是我的search
函数的版本:
datatype 'a bst = Leaf | Node of {data: 'a, left: 'a bst, right: 'a bst}
(*search(tree, compare, key) = t
where t = the tree which has `key` as its root
*)
fun search(tree : 'a bst, compare : ('a * 'a -> order), key : 'a)
: 'a bst option =
let
fun s(tree: 'a bst) : 'a bst option =
case tree of
Leaf => NONE
| Node({data=x, left=l, right=r}) =>
case compare(key,x) of
LESS => s(l)
| GREATER => s(r)
| EQUAL => SOME tree
in
s(tree)
end
(*Example:
search(Node({data=5,
left=Node({data=3,
left=Node({data=2,left=Leaf,right=Leaf}),
right=Node({data=4,left=Leaf,right=Leaf})}),
right=Leaf}),
Int.compare,
3);
*)
由于您需要一个返回搜索的父节点和祖父节点的函数,因此您需要一个返回以下元组的函数:(搜索节点,搜索节点的父节点,搜索节点的祖父节点)。但是,您不会总是有父母或祖父母。例如,如果您要查找的密钥已经位于主树的根目录中,则您将不会拥有父级或祖父级。因此,您需要使用option
类型。如果没有用于该搜索的父节点,这将帮助您将NONE
作为父节点返回。现在,您需要做的就是使用(您的主树,NONE
,NONE
)开始搜索,然后在沿树移动时,将父节点向右移动。如果找不到密钥,只需返回NONE
的三元组。这是代码:
(*searchParent(tree, compare, key) =
(t, the parent of t, the grandparent of t)
where t = the tree which has `key` as its root
*)
fun searchParent(tree : 'a bst, compare : ('a * 'a -> order), key : 'a)
: ('a bst option * 'a bst option * 'a bst option) =
let
fun s(tree: 'a bst, par: 'a bst option, gpar: 'a bst option)
: ('a bst option * 'a bst option * 'a bst option) =
case tree of
Leaf => (NONE, NONE, NONE)
| Node({data=x, left=l, right=r}) =>
case compare(key,x) of
LESS => s(l, SOME tree, par)
| GREATER => s(r, SOME tree, par)
| EQUAL => (SOME tree, par, gpar)
in
s(tree, NONE, NONE)
end
(*Example:
searchParent(Node({data=5,
left=Node({data=3,
left=Node({data=2,left=Leaf,right=Leaf}),
right=Node({data=4,left=Leaf,right=Leaf})}),
right=Leaf}),
Int.compare,
4);
*)
我希望我能提供帮助。如果您对此问题或代码有任何其他疑问,请询问。
答案 1 :(得分:0)
虽然乔恩的回答可能已经足够,但我发现它有点冗长。以下是尝试对问题进行较短的解释和回答:拥有BST和元素x
,找到两个元素(SOME parent, SOME grandparent)
(如果存在)。
我将使用的策略是:每当进行递归调用时,将parent
记录为刚刚访问过的元素,将grandparent
记录为前一个父元素。如果/当找到EQUAL
到x
的元素时,请返回当前可用的(parent, grandparent)
。
因为这两个额外的变量不是原始搜索功能的签名的一部分,并且因为我不想要它们,所以制作了本地函数helper
。
datatype 'a bst = Node of 'a * 'a bst * 'a bst
| Leaf
fun search (initTree, compare, x) =
let fun helper (tree, parent, grandparent) =
case tree of
Leaf => (NONE, NONE)
| Node (y, L, R) => case compare (x, y) of
LESS => helper (L, SOME y, parent)
| GREATER => helper (R, SOME y, parent)
| EQUAL => (parent, grandparent)
in helper (initTree, NONE, NONE) end
使用以下BST测试此功能:
val t = Node (5, Node (3, Node (2, Leaf, Leaf),
Node (4, Leaf, Leaf)),
Node (7, Node (6, Leaf, Leaf),
Node (8, Leaf, Leaf)))
我们看到了预期的结果:
- search (t, Int.compare, 2);
> val it = (SOME 3, SOME 5) : int option * int option
- search (t, Int.compare, 3);
> val it = (SOME 5, NONE) : int option * int option
不幸的是,此函数不会判断是否在BST的根目录中找到了某个元素,或者该元素是否存在。这是因为在这两种情况下都会返回(NONE, NONE)
。