Sml ML中的AVL树-向左旋转,警告:匹配非穷举

Sml ML中的AVL树-向左旋转,警告:匹配非穷举,sml,avl-tree,Sml,Avl Tree,我正在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_le

我正在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));
我从翻译那里得到:

Warning: match nonexhaustive
警告:匹配非穷举

如何使用当前的数据类型修复此问题?
我尝试使用通配符,但没有成功。

您的函数没有为具有
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)) = (* ??? *);

我对这个函数做了一些尝试,这就是我得到的有用的东西:

 fun RL node =
  case node of Br(x,A,Br(y,B,C)) => (Br(y,Br(x,A,B),C))
                             | _ => node;
我从翻译那里得到:

Warning: match nonexhaustive
如何使用当前的数据类型修复此问题?[……]

也许这一警告不应该避免。毕竟,不能旋转所有树

左旋转将如下所示:

  A              B
 / \            / \
…   B     ~>   A   C
   / \        / \ / \
  …   C      …   …   …
     / \
    …   …

给定不跟踪高度的AVL树类型

datatype 'a AVLTree = Nil | Br of 'a * 'a AVLTree * 'a AVLTree
(括号不是必需的)您的
rotate\u 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   …
                 / \
                …   ?
    
如果尝试对其中一棵树执行左旋转,则不会产生有意义的结果。具有
警告:match nonexhoustive
也不令人满意。您可以提出一个有意义的异常,例如

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(高度(左A),高度(左B))+1
和B的新高度
max(高度(新A),高度(右B))
。为此扩展
向左旋转
功能:

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位于嵌套元组中,因此可能会将树转换为从某个整数到某个“a”的映射。在这种情况下,忽略保持树中高度的优化