我正在用SML实现一个AVL树:
以下是我的数据类型:
datatype 'a AVLTree = Nil | Br of ((int*('a))*('a AVLTree)*('a AVLTree));
datatype Balance = RR | LR | LL | RL;
exception NotFound;
exception NullValue
我现在正在编写Rotate- Left函数,我将其编写如下:
fun rotate_left Nil = Nil
|rotate_left (Br(x,A,Br(y,B,C))) = (Br(y,Br(x,A,B),C));
我从口译员那里得到了:
警告:匹配非穷举
如何使用我拥有的当前数据类型解决此问题? 我尝试使用通配符,但没有成功..
答案 0 :(得分:2)
我从口译员那里得到了:
Warning: match nonexhaustive
如何使用我拥有的当前数据类型解决此问题? [...]
也许不应该避免这种警告。毕竟你不能旋转所有树木。
左旋转看起来像这样:
A B
/ \ / \
… B ~> A C
/ \ / \ / \
… C … … …
/ \
… …
给定一个不跟踪高度的AVL树类型
datatype 'a AVLTree = Nil | Br of 'a * 'a AVLTree * 'a AVLTree
(不需要括号)您的rotate_left
版本是正确的。我在下面重写了它并重命名了左右分支。有一点是B的左支行变成了A的新右支行。
fun rotate_left (Br (a, leftA, Br (b, leftB, rightB))) =
Br (b, Br (a, leftA, rightB), rightB)
这是一个部分功能,它无法匹配的模式是:
Nil
- 但空树的左旋没有明确定义。
Br (a, leftA, Nil)
- 但下面的左旋转也没有明确定义:
A ?
/ \ / \
… Nil ~> A …
/ \
… ?
如果您尝试对其中一棵树进行左旋转,则不会产生有意义的结果。拥有Warning: match nonexhaustive
也不令人满意。你可以提出一个有意义的例外,例如
fun rotate_left (Br (a, leftA, Br (b, leftB, rightB))) =
Br (b, Br (a, leftA, rightB), rightB)
| rotate_left _ = raise Fail "Invalid left-rotation"
现在,您还没有真正解释为什么在您的数据类型定义中有额外的 int 。也许这是树的预先计算的高度?这样做很整洁(你可以使用类型别名对这个含义进行编码),从那以后你的不变性检查会变得更便宜。在这种情况下,左旋转需要更新高度:
type height = int
datatype 'a AVLTree = Nil | Br of height * 'a * 'a AVLTree * 'a AVLTree
根据上图,A的新身高是max(height(leftA), height(leftB)) + 1
,B是新身高max(height(new A), height(rightB))
。为此扩展rotate_left
函数:
fun height Nil = 0
| height (Br (h, _, _, _)) = h
fun rotate_left (Br (ha, a, leftA, Br (hb, b, leftB, rightB))) =
let val ha' = Int.max (height leftA, height leftB) + 1
val hb' = Int.max (ha', height rightB) + 1
in Br (hb', b, Br (ha', a, leftA, rightB), rightB) end
| rotate_left _ = raise Fail "Invalid left-rotation"
编辑:我发现额外的 int 在嵌套元组中,因此可能会将树转换为从某个整数到某些&的映射#39;一个。在这种情况下,忽略保持树高度的优化。
答案 1 :(得分:1)
没有为形状为Br(x, A, NIL)
的值定义您的函数。
在这种情况下会发生什么?
fun rotate_left Nil = Nil
| rotate_left (Br(x,A,Br(y,B,C))) = (Br(y,Br(x,A,B),C))
| rotate_left (Br(x, A, Nil)) = (* ??? *);
答案 2 :(得分:0)
我玩了一下这个功能,这就是我的功能:
fun RL node =
case node of Br(x,A,Br(y,B,C)) => (Br(y,Br(x,A,B),C))
| _ => node;