CS 312 Lecture 13:
AVL Trees

 

AVL trees have been invented by Adelson-Velskii and Landis in 1962. An AVL tree is a balanced binary search tree where every node in the tree satisfies the following invariant: the height difference between its left and right children is at most 1. Hence, all sub-trees of an AVL tree are themselves AVL. The height difference between children is referred to as the balance factor of the node.

type height = int
type data = int
datatype avltree = Nil | Node of height * data * avltree * avltree

(* Rep Invariant:
 * (1) BST invariant: each node Node(h, v, l, r) is such that
 *     v is greater than all values in l, and less than all values in r
 * (2) each node is balanced, i.e., abs(l.h - r.h) <= 1
 *)

fun height(Nil) = 0
  | height(Node(h,_,_,_)) = h

fun bal_factor(Nil) = 0
  | bal_factor(Node(_,_,l,r)) = (height l) - (height r)

fun node(v: data, l: avltree, r: avltree): avltree =
  Node(1+Int.max(height l, height r), v, l, r)

fun rotate_left(t: avltree): avltree =
  case t 
    of Node(_, x, a, Node(_, y, b, c)) => node(y, node(x, a, b), c)
     | _ => t

fun rotate_right(t: avltree): avltree =
  case t
    of Node(_, x, Node(_, y, a, b), c) => node(y, a, node(x, b, c))
     | _ => t

fun balance(n as Node(h, v, l, r): avltree): avltree =
  case (bal_factor n, bal_factor l, bal_factor r) 
    of ( 2, ~1, _) => rotate_right(node(v, rotate_left l, r))
     | ( 2, _, _)  => rotate_right(n)
     | (~2, _, 1)  => rotate_left (node(v, l, rotate_right r))
     | (~2, _, _)  => rotate_left (n)
     | _ => n

fun insert (t: avltree, n:int): avltree =
  case t
    of Nil => node(n, Nil, Nil)
     | Node(h, v, l, r) =>
         case Int.compare (n, v)
           of EQUAL => t
            | LESS => balance(node(v, insert(l, n), r))
            | GREATER => balance(node(v, l, insert(r, n)))

fun delete(t: avltree, n: int): avltree =
  let
    fun deleteSuccessor(t: avltree): avltree*int =
      case t
        of Nil => raise Fail "impossible"
         | Node(_, v, Nil, r) => (r, v)
         | Node(_, v, l, r) => let val (l', v') = deleteSuccessor(l)
                               in (balance(node(v, l', r)), v') end
  in
    case t
      of Nil => raise Fail "value not in the tree"
       | Node (_, v, l, r) =>
           case Int.compare(n, v)
             of LESS => balance(node(v, delete(l, n), r))
              | GREATER => balance(node(v, l, delete(r, n)))
              | EQUAL => case (l, r)
                           of (_, Nil) => l
                            | (Nil, _) => r
                            | _ => let val (r', v') = deleteSuccessor(r)
                                   in balance(node(v', l, r')) end
  end