AVL tree

From Rosetta Code
AVL tree is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at AVL tree. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)

In computer science, an AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.

AVL trees are often compared with red-black trees because they support the same set of operations and because red-black trees also take O(log n) time for the basic operations. Because AVL trees are more rigidly balanced, they are faster than red-black trees for lookup-intensive applications. Similar to red-black trees, AVL trees are height-balanced, but in general not weight-balanced nor μ-balanced; that is, sibling nodes can have hugely differing numbers of descendants.

Task: Implement an AVL tree in the language of choice and provide at least basic operations.

Agda

This implementation uses the type system to enforce the height invariants, though not the BST invariants <lang agda> module Avl where

-- The Peano naturals data Nat : Set where

z : Nat
s : Nat -> Nat

-- An AVL tree's type is indexed by a natural. -- Avl N is the type of AVL trees of depth N. There arj 3 different -- node constructors: -- Left: The left subtree is one level deeper than the right -- Balanced: The subtrees have the same depth -- Right: The right Subtree is one level deeper than the left -- Since the AVL invariant is that the depths of a node's subtrees -- always differ by at most 1, this perfectly encodes the AVL depth invariant. data Avl : Nat -> Set where

 Empty : Avl z
 Left : {X : Nat} -> Nat -> Avl (s X) -> Avl X -> Avl (s (s X))
 Balanced : {X : Nat} -> Nat -> Avl X -> Avl X -> Avl (s X)
 Right : {X : Nat} -> Nat -> Avl X -> Avl (s X) -> Avl (s (s X))

-- A wrapper type that hides the AVL tree invariant. This is the interface -- exposed to the user. data Tree : Set where

 avl : {N : Nat} -> Avl N -> Tree

-- Comparison result data Ord : Set where

 Less : Ord
 Equal : Ord
 Greater : Ord

-- Comparison function cmp : Nat -> Nat -> Ord cmp z (s X) = Less cmp z z = Equal cmp (s X) z = Greater cmp (s X) (s Y) = cmp X Y

-- Insertions can either leave the depth the same or -- increase it by one. Encode this in the type. data InsertResult : Nat -> Set where

 Same : {X : Nat} -> Avl X -> InsertResult X
 Bigger : {X : Nat} -> Avl (s X) -> InsertResult X

-- If the left subtree is 2 levels deeper than the right, rotate to the right. -- balance-left X L R means X is the root, L is the left subtree and R is the right. balance-left : {N : Nat} -> Nat -> Avl (s (s N)) -> Avl N -> InsertResult (s (s N)) balance-left X (Right Y A (Balanced Z B C)) D = Same (Balanced Z (Balanced X A B) (Balanced Y C D)) balance-left X (Right Y A (Left Z B C)) D = Same (Balanced Z (Balanced X A B) (Right Y C D)) balance-left X (Right Y A (Right Z B C)) D = Same (Balanced Z (Left X A B) (Balanced Y C D)) balance-left X (Left Y (Balanced Z A B) C) D = Same (Balanced Z (Balanced X A B) (Balanced Y C D)) balance-left X (Left Y (Left Z A B) C) D = Same (Balanced Z (Left X A B) (Balanced Y C D)) balance-left X (Left Y (Right Z A B) C) D = Same (Balanced Z (Right X A B) (Balanced Y C D)) balance-left X (Balanced Y (Balanced Z A B) C) D = Bigger (Right Z (Balanced X A B) (Left Y C D)) balance-left X (Balanced Y (Left Z A B) C) D = Bigger (Right Z (Left X A B) (Left Y C D)) balance-left X (Balanced Y (Right Z A B) C) D = Bigger (Right Z (Right X A B) (Left Y C D))

-- Symmetric with balance-left balance-right : {N : Nat} -> Nat -> Avl N -> Avl (s (s N)) -> InsertResult (s (s N)) balance-right X A (Left Y (Left Z B C) D) = Same (Balanced Z (Balanced X A B) (Right Y C D)) balance-right X A (Left Y (Balanced Z B C) D) = Same(Balanced Z (Balanced X A B) (Balanced Y C D)) balance-right X A (Left Y (Right Z B C) D) = Same(Balanced Z (Left X A B) (Balanced Y C D)) balance-right X A (Balanced Z B (Left Y C D)) = Bigger(Left Z (Right X A B) (Left Y C D)) balance-right X A (Balanced Z B (Balanced Y C D)) = Bigger (Left Z (Right X A B) (Balanced Y C D)) balance-right X A (Balanced Z B (Right Y C D)) = Bigger (Left Z (Right X A B) (Right Y C D)) balance-right X A (Right Z B (Left Y C D)) = Same (Balanced Z (Balanced X A B) (Left Y C D)) balance-right X A (Right Z B (Balanced Y C D)) = Same (Balanced Z (Balanced X A B) (Balanced Y C D)) balance-right X A (Right Z B (Right Y C D)) = Same (Balanced Z (Balanced X A B) (Right Y C D))

-- insert' T N does all the work of inserting the element N into the tree T. insert' : {N : Nat} -> Avl N -> Nat -> InsertResult N insert' Empty N = Bigger (Balanced N Empty Empty) insert' (Left Y L R) X with cmp X Y insert' (Left Y L R) X | Less with insert' L X insert' (Left Y L R) X | Less | Same L' = Same (Left Y L' R) insert' (Left Y L R) X | Less | Bigger L' = balance-left Y L' R insert' (Left Y L R) X | Equal = Same (Left Y L R) insert' (Left Y L R) X | Greater with insert' R X insert' (Left Y L R) X | Greater | Same R' = Same (Left Y L R') insert' (Left Y L R) X | Greater | Bigger R' = Same (Balanced Y L R') insert' (Balanced Y L R) X with cmp X Y insert' (Balanced Y L R) X | Less with insert' L X insert' (Balanced Y L R) X | Less | Same L' = Same (Balanced Y L' R) insert' (Balanced Y L R) X | Less | Bigger L' = Bigger (Left Y L' R) insert' (Balanced Y L R) X | Equal = Same (Balanced Y L R) insert' (Balanced Y L R) X | Greater with insert' R X insert' (Balanced Y L R) X | Greater | Same R' = Same (Balanced Y L R') insert' (Balanced Y L R) X | Greater | Bigger R' = Bigger (Right Y L R') insert' (Right Y L R) X with cmp X Y insert' (Right Y L R) X | Less with insert' L X insert' (Right Y L R) X | Less | Same L' = Same (Right Y L' R) insert' (Right Y L R) X | Less | Bigger L' = Same (Balanced Y L' R) insert' (Right Y L R) X | Equal = Same (Right Y L R) insert' (Right Y L R) X | Greater with insert' R X insert' (Right Y L R) X | Greater | Same R' = Same (Right Y L R') insert' (Right Y L R) X | Greater | Bigger R' = balance-right Y L R'

-- Wrapper around insert' to use the depth-agnostic type Tree. insert : Tree -> Nat -> Tree insert (avl T) X with insert' T X ... | Same T' = avl T' ... | Bigger T' = avl T' </lang>


C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <time.h>

struct node { int payload; int height; struct node * kid[2]; } dummy = { 0, 0, {&dummy, &dummy} }, *nnil = &dummy; // internally, nnil is the new nul

struct node *new_node(int value) { struct node *n = calloc(1, sizeof *n); *n = (struct node) { value, 1, {nnil, nnil} }; return n; }

int max(int a, int b) { return a > b ? a : b; } inline void set_height(struct node *n) { n->height = 1 + max(n->kid[0]->height, n->kid[1]->height); }

inline int ballance(struct node *n) { return n->kid[0]->height - n->kid[1]->height; }

// rotate a subtree according to dir; if new root is nil, old root is freed struct node * rotate(struct node **rootp, int dir) { struct node *old_r = *rootp, *new_r = old_r->kid[dir];

if (nnil == (*rootp = new_r)) free(old_r); else { old_r->kid[dir] = new_r->kid[!dir]; set_height(old_r); new_r->kid[!dir] = old_r; } return new_r; }

void adjust_balance(struct node **rootp) { struct node *root = *rootp; int b = ballance(root)/2; if (b) { int dir = (1 - b)/2; if (ballance(root->kid[dir]) == -b) rotate(&root->kid[dir], !dir); root = rotate(rootp, dir); } if (root != nnil) set_height(root); }

// find the node that contains value as payload; or returns 0 struct node *query(struct node *root, int value) { return root == nnil ? 0 : root->payload == value ? root : query(root->kid[value > root->payload], value); }

void insert(struct node **rootp, int value) { struct node *root = *rootp;

if (root == nnil) *rootp = new_node(value); else if (value != root->payload) { // don't allow dup keys insert(&root->kid[value > root->payload], value); adjust_balance(rootp); } }

void delete(struct node **rootp, int value) { struct node *root = *rootp; if (root == nnil) return; // not found

// if this is the node we want, rotate until off the tree if (root->payload == value) if (nnil == (root = rotate(rootp, ballance(root) < 0))) return;

delete(&root->kid[value > root->payload], value); adjust_balance(rootp); }

// aux display and verification routines, helpful but not essential struct trunk { struct trunk *prev; char * str; };

void show_trunks(struct trunk *p) { if (!p) return; show_trunks(p->prev); printf("%s", p->str); }

// this is very haphazzard void show_tree(struct node *root, struct trunk *prev, int is_left) { if (root == nnil) return;

struct trunk this_disp = { prev, " " }; char *prev_str = this_disp.str; show_tree(root->kid[0], &this_disp, 1);

if (!prev) this_disp.str = "---"; else if (is_left) { this_disp.str = ".--"; prev_str = " |"; } else { this_disp.str = "`--"; prev->str = prev_str; }

show_trunks(&this_disp); printf("%d\n", root->payload);

if (prev) prev->str = prev_str; this_disp.str = " |";

show_tree(root->kid[1], &this_disp, 0); if (!prev) puts(""); }

int verify(struct node *p) { if (p == nnil) return 1;

int h0 = p->kid[0]->height, h1 = p->kid[1]->height; int b = h0 - h1;

if (p->height != 1 + max(h0, h1) || b < -1 || b > 1) { printf("node %d bad, balance %d\n", p->payload, b); show_tree(p, 0, 0); abort(); } return verify(p->kid[0]) && verify(p->kid[1]); }

  1. define MAX_VAL 32

int main(void) { int x; struct node *root = nnil;

srand(time(0));

for (x = 0; x < 10 * MAX_VAL; x++) { // random insertion and deletion if (rand()&1) insert(&root, rand()%MAX_VAL); else delete(&root, rand()%MAX_VAL);

verify(root); }

puts("Tree is:"); show_tree(root, 0, 0);

puts("\nQuerying values:"); for (x = 0; x < MAX_VAL; x++) { struct node *p = query(root, x); if (p) printf("%2d found: %p %d\n", x, p, p->payload); }

for (x = 0; x < MAX_VAL; x++) { delete(&root, x); verify(root); }

puts("\nAfter deleting all values, tree is:"); show_tree(root, 0, 0);

return 0; }</lang>

Output:
Tree is:
            .--0
        .--2
       |    `--4
       |        `--5
    .--6
   |   |    .--10
   |    `--12
   |       |    .--13
   |        `--15
---17
   |            .--18
   |        .--19
   |    .--21
   |   |   |    .--24
   |   |    `--25
    `--26
        `--27
            `--30


Querying values:
 0 found: 0x180a210 0
 2 found: 0x180a1b0 2
 4 found: 0x180a010 4
 5 found: 0x180a0d0 5
 6 found: 0x180a0f0 6
10 found: 0x180a190 10
12 found: 0x180a150 12
13 found: 0x180a250 13
15 found: 0x180a050 15
17 found: 0x180a270 17
18 found: 0x180a1d0 18
19 found: 0x180a170 19
21 found: 0x180a070 21
24 found: 0x180a030 24
25 found: 0x180a0b0 25
26 found: 0x180a130 26
27 found: 0x180a1f0 27
30 found: 0x180a110 30

After deleting all values, tree is:

C++

Translation of: D

<lang cpp>

  1. include <algorithm>
  2. include <iostream>

/* AVL node */ template <class T> class AVLnode { public:

   T key;
   int balance;
   AVLnode *left, *right, *parent;
   AVLnode(T k, AVLnode *p) : key(k), balance(0), parent(p),
                       left(NULL), right(NULL) {}
   ~AVLnode() {
       delete left;
       delete right;
   }

};

/* AVL tree */ template <class T> class AVLtree { public:

   AVLtree(void);
   ~AVLtree(void);
   bool insert(T key);
   void deleteKey(const T key);
   void printBalance();

private:

   AVLnode<T> *root;
   AVLnode<T>* rotateLeft          ( AVLnode<T> *a );
   AVLnode<T>* rotateRight         ( AVLnode<T> *a );
   AVLnode<T>* rotateLeftThenRight ( AVLnode<T> *n );
   AVLnode<T>* rotateRightThenLeft ( AVLnode<T> *n );
   void rebalance                  ( AVLnode<T> *n );
   int height                      ( AVLnode<T> *n );
   void setBalance                 ( AVLnode<T> *n );
   void printBalance               ( AVLnode<T> *n );
   void clearNode                  ( AVLnode<T> *n );

};

/* AVL class definition */ template <class T> void AVLtree<T>::rebalance(AVLnode<T> *n) {

   setBalance(n);
   if (n->balance == -2) {
       if (height(n->left->left) >= height(n->left->right))
           n = rotateRight(n);
       else
           n = rotateLeftThenRight(n);
   }
   else if (n->balance == 2) {
       if (height(n->right->right) >= height(n->right->left))
           n = rotateLeft(n);
       else
           n = rotateRightThenLeft(n);
   }
   if (n->parent != NULL) {
       rebalance(n->parent);
   }
   else {
       root = n;
   }

}

template <class T> AVLnode<T>* AVLtree<T>::rotateLeft(AVLnode<T> *a) {

   AVLnode<T> *b = a->right;
   b->parent = a->parent;
   a->right = b->left;
   if (a->right != NULL)
       a->right->parent = a;
   b->left = a;
   a->parent = b;
   if (b->parent != NULL) {
       if (b->parent->right == a) {
           b->parent->right = b;
       }
       else {
           b->parent->left = b;
       }
   }
   setBalance(a);
   setBalance(b);
   return b;

}

template <class T> AVLnode<T>* AVLtree<T>::rotateRight(AVLnode<T> *a) {

   AVLnode<T> *b = a->left;
   b->parent = a->parent;
   a->left = b->right;
   if (a->left != NULL)
       a->left->parent = a;
   b->right = a;
   a->parent = b;
   if (b->parent != NULL) {
       if (b->parent->right == a) {
           b->parent->right = b;
       }
       else {
           b->parent->left = b;
       }
   }
   setBalance(a);
   setBalance(b);
   return b;

}

template <class T> AVLnode<T>* AVLtree<T>::rotateLeftThenRight(AVLnode<T> *n) {

   n->left = rotateLeft(n->left);
   return rotateRight(n);

}

template <class T> AVLnode<T>* AVLtree<T>::rotateRightThenLeft(AVLnode<T> *n) {

   n->right = rotateRight(n->right);
   return rotateLeft(n);

}

template <class T> int AVLtree<T>::height(AVLnode<T> *n) {

   if (n == NULL)
       return -1;
   return 1 + std::max(height(n->left), height(n->right));

}

template <class T> void AVLtree<T>::setBalance(AVLnode<T> *n) {

   n->balance = height(n->right) - height(n->left);

}

template <class T> void AVLtree<T>::printBalance(AVLnode<T> *n) {

   if (n != NULL) {
       printBalance(n->left);
       std::cout << n->balance << " ";
       printBalance(n->right);
   }

}

template <class T> AVLtree<T>::AVLtree(void) : root(NULL) {}

template <class T> AVLtree<T>::~AVLtree(void) {

   delete root;

}

template <class T> bool AVLtree<T>::insert(T key) {

   if (root == NULL) {
       root = new AVLnode<T>(key, NULL);
   }
   else {
       AVLnode<T>
           *n = root,
           *parent;
       while (true) {
           if (n->key == key)
               return false;
           parent = n;
           bool goLeft = n->key > key;
           n = goLeft ? n->left : n->right;
           if (n == NULL) {
               if (goLeft) {
                   parent->left = new AVLnode<T>(key, parent);
               }
               else {
                   parent->right = new AVLnode<T>(key, parent);
               }
               rebalance(parent);
               break;
           }
       }
   }
   return true;

}

template <class T> void AVLtree<T>::deleteKey(const T delKey) {

   if (root == NULL)
       return;
   AVLnode<T>
       *n       = root,
       *parent  = root,
       *delNode = NULL,
       *child   = root;
   while (child != NULL) {
       parent = n;
       n = child;
       child = delKey >= n->key ? n->right : n->left;
       if (delKey == n->key)
           delNode = n;
   }
   if (delNode != NULL) {
       delNode->key = n->key;
       child = n->left != NULL ? n->left : n->right;
       if (root->key == delKey) {
           root = child;
       }
       else {
           if (parent->left == n) {
               parent->left = child;
           }
           else {
               parent->right = child;
           }
           rebalance(parent);
       }
   }

}

template <class T> void AVLtree<T>::printBalance() {

   printBalance(root);
   std::cout << std::endl;

}

int main(void) {

   AVLtree<int> t;
   std::cout << "Inserting integer values 1 to 10" << std::endl;
   for (int i = 1; i <= 10; ++i)
       t.insert(i);
   std::cout << "Printing balance: ";
   t.printBalance();

} </lang>

Output:
Inserting integer values 1 to 10
Printing balance: 0 0 0 1 0 0 0 0 1 0 

D

Translation of: Java

<lang d>import std.stdio, std.algorithm;

class AVLtree {

   private Node* root;
   private static struct Node {
       private int key, balance;
       private Node* left, right, parent;
       this(in int k, Node* p) pure nothrow @safe @nogc {
           key = k;
           parent = p;
       }
   }
   public bool insert(in int key) pure nothrow @safe {
       if (root is null)
           root = new Node(key, null);
       else {
           Node* n = root;
           Node* parent;
           while (true) {
               if (n.key == key)
                   return false;
               parent = n;
               bool goLeft = n.key > key;
               n = goLeft ? n.left : n.right;
               if (n is null) {
                   if (goLeft) {
                       parent.left = new Node(key, parent);
                   } else {
                       parent.right = new Node(key, parent);
                   }
                   rebalance(parent);
                   break;
               }
           }
       }
       return true;
   }
   public void deleteKey(in int delKey) pure nothrow @safe @nogc {
       if (root is null)
           return;
       Node* n = root;
       Node* parent = root;
       Node* delNode = null;
       Node* child = root;
       while (child !is null) {
           parent = n;
           n = child;
           child = delKey >= n.key ? n.right : n.left;
           if (delKey == n.key)
               delNode = n;
       }
       if (delNode !is null) {
           delNode.key = n.key;
           child = n.left !is null ? n.left : n.right;
           if (root.key == delKey) {
               root = child;
           } else {
               if (parent.left is n) {
                   parent.left = child;
               } else {
                   parent.right = child;
               }
               rebalance(parent);
           }
       }
   }
   private void rebalance(Node* n) pure nothrow @safe @nogc {
       setBalance(n);
       if (n.balance == -2) {
           if (height(n.left.left) >= height(n.left.right))
               n = rotateRight(n);
           else
               n = rotateLeftThenRight(n);
       } else if (n.balance == 2) {
           if (height(n.right.right) >= height(n.right.left))
               n = rotateLeft(n);
           else
               n = rotateRightThenLeft(n);
       }
       if (n.parent !is null) {
           rebalance(n.parent);
       } else {
           root = n;
       }
   }
   private Node* rotateLeft(Node* a) pure nothrow @safe @nogc {
       Node* b = a.right;
       b.parent = a.parent;
       a.right = b.left;
       if (a.right !is null)
           a.right.parent = a;
       b.left = a;
       a.parent = b;
       if (b.parent !is null) {
           if (b.parent.right is a) {
               b.parent.right = b;
           } else {
               b.parent.left = b;
           }
       }
       setBalance(a, b);
       return b;
   }
   private Node* rotateRight(Node* a) pure nothrow @safe @nogc {
       Node* b = a.left;
       b.parent = a.parent;
       a.left = b.right;
       if (a.left !is null)
           a.left.parent = a;
       b.right = a;
       a.parent = b;
       if (b.parent !is null) {
           if (b.parent.right is a) {
               b.parent.right = b;
           } else {
               b.parent.left = b;
           }
       }
       setBalance(a, b);
       return b;
   }
   private Node* rotateLeftThenRight(Node* n) pure nothrow @safe @nogc {
       n.left = rotateLeft(n.left);
       return rotateRight(n);
   }
   private Node* rotateRightThenLeft(Node* n) pure nothrow @safe @nogc {
       n.right = rotateRight(n.right);
       return rotateLeft(n);
   }
   private int height(in Node* n) const pure nothrow @safe @nogc {
       if (n is null)
           return -1;
       return 1 + max(height(n.left), height(n.right));
   }
   private void setBalance(Node*[] nodes...) pure nothrow @safe @nogc {
       foreach (n; nodes)
           n.balance = height(n.right) - height(n.left);
   }
   public void printBalance() const @safe {
       printBalance(root);
   }
   private void printBalance(in Node* n) const @safe {
       if (n !is null) {
           printBalance(n.left);
           write(n.balance, ' ');
           printBalance(n.right);
       }
   }

}

void main() @safe {

   auto tree = new AVLtree();
   writeln("Inserting values 1 to 10");
   foreach (immutable i; 1 .. 11)
       tree.insert(i);
   write("Printing balance: ");
   tree.printBalance;

}</lang>

Output:
Inserting values 1 to 10
Printing balance: 0 0 0 1 0 0 0 0 1 0 

Java

This code has been cobbled together from various online examples. It's not easy to find a clear and complete explanation of AVL trees. Textbooks tend to concentrate on red-black trees because of their better efficiency. (AVL trees need to make 2 passes through the tree when inserting and deleting: one down to find the node to operate upon and one up to rebalance the tree.) <lang java>public class AVLtree {

   private Node root;
   private class Node {
       private int key;
       private int balance;
       private Node left, right, parent;
       Node(int k, Node p) {
           key = k;
           parent = p;
       }
   }
   public boolean insert(int key) {
       if (root == null)
           root = new Node(key, null);
       else {
           Node n = root;
           Node parent;
           while (true) {
               if (n.key == key)
                   return false;
               parent = n;
               boolean goLeft = n.key > key;
               n = goLeft ? n.left : n.right;
               if (n == null) {
                   if (goLeft) {
                       parent.left = new Node(key, parent);
                   } else {
                       parent.right = new Node(key, parent);
                   }
                   rebalance(parent);
                   break;
               }
           }
       }
       return true;
   }
   public void delete(int delKey) {
       if (root == null)
           return;
       Node n = root;
       Node parent = root;
       Node delNode = null;
       Node child = root;
       while (child != null) {
           parent = n;
           n = child;
           child = delKey >= n.key ? n.right : n.left;
           if (delKey == n.key)
               delNode = n;
       }
       if (delNode != null) {
           delNode.key = n.key;
           child = n.left != null ? n.left : n.right;
           if (root.key == delKey) {
               root = child;
           } else {
               if (parent.left == n) {
                   parent.left = child;
               } else {
                   parent.right = child;
               }
               rebalance(parent);
           }
       }
   }
   private void rebalance(Node n) {
       setBalance(n);
       if (n.balance == -2) {
           if (height(n.left.left) >= height(n.left.right))
               n = rotateRight(n);
           else
               n = rotateLeftThenRight(n);
       } else if (n.balance == 2) {
           if (height(n.right.right) >= height(n.right.left))
               n = rotateLeft(n);
           else
               n = rotateRightThenLeft(n);
       }
       if (n.parent != null) {
           rebalance(n.parent);
       } else {
           root = n;
       }
   }
   private Node rotateLeft(Node a) {
       Node b = a.right;
       b.parent = a.parent;
       a.right = b.left;
       if (a.right != null)
           a.right.parent = a;
       b.left = a;
       a.parent = b;
       if (b.parent != null) {
           if (b.parent.right == a) {
               b.parent.right = b;
           } else {
               b.parent.left = b;
           }
       }
       setBalance(a, b);
       return b;
   }
   private Node rotateRight(Node a) {
       Node b = a.left;
       b.parent = a.parent;
       a.left = b.right;
       if (a.left != null)
           a.left.parent = a;
       b.right = a;
       a.parent = b;
       if (b.parent != null) {
           if (b.parent.right == a) {
               b.parent.right = b;
           } else {
               b.parent.left = b;
           }
       }
       setBalance(a, b);
       return b;
   }
   private Node rotateLeftThenRight(Node n) {
       n.left = rotateLeft(n.left);
       return rotateRight(n);
   }
   private Node rotateRightThenLeft(Node n) {
       n.right = rotateRight(n.right);
       return rotateLeft(n);
   }
   private int height(Node n) {
       if (n == null)
           return -1;
       return 1 + Math.max(height(n.left), height(n.right));
   }
   private void setBalance(Node... nodes) {
       for (Node n : nodes)
           n.balance = height(n.right) - height(n.left);
   }
   public void printBalance() {
       printBalance(root);
   }
   private void printBalance(Node n) {
       if (n != null) {
           printBalance(n.left);
           System.out.printf("%s ", n.balance);
           printBalance(n.right);
       }
   }
   public static void main(String[] args) {
       AVLtree tree = new AVLtree();
       System.out.println("Inserting values 1 to 10");
       for (int i = 1; i < 10; i++)
           tree.insert(i);
       System.out.print("Printing balance: ");
       tree.printBalance();
   }

}</lang>

Inserting values 1 to 10
Printing balance: 0 0 0 1 0 1 0 0 0

Go

A package: <lang go>package avl

// AVL tree adapted from Julienne Walker's presentation at // http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_avl.aspx. // This port uses similar indentifier names.

// The Key interface must be supported by data stored in the AVL tree. type Key interface {

   Less(Key) bool
   Eq(Key) bool

}

// Node is a node in an AVL tree. type Node struct {

   Data    Key      // anything comparable with Less and Eq.
   Balance int      // balance factor
   Link    [2]*Node // children, indexed by "direction", 0 or 1.

}

// A little readability function for returning the opposite of a direction, // where a direction is 0 or 1. Go inlines this. // Where JW writes !dir, this code has opp(dir). func opp(dir int) int {

   return 1 - dir

}

// single rotation func single(root *Node, dir int) *Node {

   save := root.Link[opp(dir)]
   root.Link[opp(dir)] = save.Link[dir]
   save.Link[dir] = root
   return save

}

// double rotation func double(root *Node, dir int) *Node {

   save := root.Link[opp(dir)].Link[dir]
   root.Link[opp(dir)].Link[dir] = save.Link[opp(dir)]
   save.Link[opp(dir)] = root.Link[opp(dir)]
   root.Link[opp(dir)] = save
   save = root.Link[opp(dir)]
   root.Link[opp(dir)] = save.Link[dir]
   save.Link[dir] = root
   return save

}

// adjust valance factors after double rotation func adjustBalance(root *Node, dir, bal int) {

   n := root.Link[dir]
   nn := n.Link[opp(dir)]
   switch nn.Balance {
   case 0:
       root.Balance = 0
       n.Balance = 0
   case bal:
       root.Balance = -bal
       n.Balance = 0
   default:
       root.Balance = 0
       n.Balance = bal
   }
   nn.Balance = 0

}

func insertBalance(root *Node, dir int) *Node {

   n := root.Link[dir]
   bal := 2*dir - 1
   if n.Balance == bal {
       root.Balance = 0
       n.Balance = 0
       return single(root, opp(dir))
   }
   adjustBalance(root, dir, bal)
   return double(root, opp(dir))

}

func insertR(root *Node, data Key) (*Node, bool) {

   if root == nil {
       return &Node{Data: data}, false
   }
   dir := 0
   if root.Data.Less(data) {
       dir = 1
   }
   var done bool
   root.Link[dir], done = insertR(root.Link[dir], data)
   if done {
       return root, true
   }
   root.Balance += 2*dir - 1
   switch root.Balance {
   case 0:
       return root, true
   case 1, -1:
       return root, false
   }
   return insertBalance(root, dir), true

}

// Insert a node into the AVL tree. // Data is inserted even if other data with the same key already exists. func Insert(tree **Node, data Key) {

   *tree, _ = insertR(*tree, data)

}

func removeBalance(root *Node, dir int) (*Node, bool) {

   n := root.Link[opp(dir)]
   bal := 2*dir - 1
   switch n.Balance {
   case -bal:
       root.Balance = 0
       n.Balance = 0
       return single(root, dir), false
   case bal:
       adjustBalance(root, opp(dir), -bal)
       return double(root, dir), false
   }
   root.Balance = -bal
   n.Balance = bal
   return single(root, dir), true

}

func removeR(root *Node, data Key) (*Node, bool) {

   if root == nil {
       return nil, false
   }
   if root.Data.Eq(data) {
       switch {
       case root.Link[0] == nil:
           return root.Link[1], false
       case root.Link[1] == nil:
           return root.Link[0], false
       }
       heir := root.Link[0]
       for heir.Link[1] != nil {
           heir = heir.Link[1]
       }
       root.Data = heir.Data
       data = heir.Data
   }
   dir := 0
   if root.Data.Less(data) {
       dir = 1
   }
   var done bool
   root.Link[dir], done = removeR(root.Link[dir], data)
   if done {
       return root, true
   }
   root.Balance += 1 - 2*dir
   switch root.Balance {
   case 1, -1:
       return root, true
   case 0:
       return root, false
   }
   return removeBalance(root, dir)

}

// Remove a single item from an AVL tree. // If key does not exist, function has no effect. func Remove(tree **Node, data Key) {

   *tree, _ = removeR(*tree, data)

}</lang> A demonstration program: <lang go>package main

import (

   "encoding/json"
   "fmt"
   "log"
   "avl"

)

type intKey int

// satisfy avl.Key func (k intKey) Less(k2 avl.Key) bool { return k < k2.(intKey) } func (k intKey) Eq(k2 avl.Key) bool { return k == k2.(intKey) }

// use json for cheap tree visualization func dump(tree *avl.Node) {

   b, err := json.MarshalIndent(tree, "", "   ")
   if err != nil {
       log.Fatal(err)
   }
   fmt.Println(string(b))

}

func main() {

   var tree *avl.Node
   fmt.Println("Empty tree:")
   dump(tree)
   fmt.Println("\nInsert test:")
   avl.Insert(&tree, intKey(3))
   avl.Insert(&tree, intKey(1))
   avl.Insert(&tree, intKey(4))
   avl.Insert(&tree, intKey(1))
   avl.Insert(&tree, intKey(5))
   dump(tree)
   fmt.Println("\nRemove test:")
   avl.Remove(&tree, intKey(3))
   avl.Remove(&tree, intKey(1))
   dump(tree)

}</lang>

Output:
Empty tree:
null

Insert test:
{
   "Data": 3,
   "Balance": 0,
   "Link": [
      {
         "Data": 1,
         "Balance": -1,
         "Link": [
            {
               "Data": 1,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            },
            null
         ]
      },
      {
         "Data": 4,
         "Balance": 1,
         "Link": [
            null,
            {
               "Data": 5,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            }
         ]
      }
   ]
}

Remove test:
{
   "Data": 4,
   "Balance": 0,
   "Link": [
      {
         "Data": 1,
         "Balance": 0,
         "Link": [
            null,
            null
         ]
      },
      {
         "Data": 5,
         "Balance": 0,
         "Link": [
            null,
            null
         ]
      }
   ]
}

Haskell

Solution of homework #4 from course http://www.seas.upenn.edu/~cis194/spring13/lectures.html. <lang haskell>data Tree a = Leaf | Node Int (Tree a) a (Tree a)

 deriving (Show, Eq)

foldTree :: Ord a => [a] -> Tree a foldTree = foldr insert Leaf

height Leaf = -1 height (Node h _ _ _) = h

depth a b = 1 + (height a `max` height b)

insert :: Ord a => a -> Tree a -> Tree a insert v Leaf = Node 1 Leaf v Leaf insert v t@(Node n left v' right)

   | v' < v = rotate $ Node n left v' (insert v right)
   | v' > v = rotate $ Node n (insert v left) v' right
   | otherwise = t

max' :: Ord a => Tree a -> Maybe a max' Leaf = Nothing max' (Node _ _ v right) = case right of

                              Leaf -> Just v
                              _    -> max' right

delete :: Ord a => a -> Tree a -> Tree a delete _ Leaf = Leaf delete x (Node h left v right)

   | x == v = maybe left (\m -> rotate $ Node h left m (delete m right)) (max' right)
   | x > v  = rotate $ Node h left v (delete x right)
   | x < v  = rotate $ Node h (delete x left) v right 

rotate :: Tree a -> Tree a rotate Leaf = Leaf -- left left case rotate (Node h (Node lh ll lv lr) v r)

   | lh - height r > 1 && height ll - height lr > 0 = 
     Node lh ll lv (Node (depth r lr) lr v r)

-- right right case rotate (Node h l v (Node rh rl rv rr))

   | rh - height l > 1 && height rr - height rl > 0 =
     Node rh (Node (depth l rl) l v rl) rv rr

-- left right case rotate (Node h (Node lh ll lv (Node rh rl rv rr)) v r)

   | lh - height r > 1 = Node h (Node (rh+1) (Node (lh-1) ll lv rl) rv rr) v r

-- right left case rotate (Node h l v (Node rh (Node lh ll lv lr) rv rr))

   | rh - height l > 1 = Node h l v (Node (lh+1) ll lv (Node (rh-1) lr rv rr))

-- re-weighting rotate (Node h l v r) = let (l', r') = (rotate l, rotate r)

                       in Node (depth l' r') l' v r'

draw :: Show a => Tree a -> String draw t = "\n" ++ draw' t 0 ++ "\n"

 where
   draw' Leaf _ = []
   draw' (Node h l v r) d = draw' r (d+1) ++ node ++ draw' l (d+1)
     where
       node = padding d ++ show (v, h) ++ "\n"
       padding n = replicate (n*4) ' '</lang>
*Main> putStr $ draw $ foldTree [1..15]

            (15,0)
        (14,1)
            (13,0)
    (12,2)
            (11,0)
        (10,1)
            (9,0)
(8,3)
            (7,0)
        (6,1)
            (5,0)
    (4,2)
            (3,0)
        (2,1)
            (1,0)

Scheme

Pure functional version. Explanative article in Russian, written by Swizard.

Tcl

Note that in general, you would not normally write a tree directly in Tcl when writing code that required an = map, but would rather use either an array variable or a dictionary value (which are internally implemented using a high-performance hash table engine).

Works with: Tcl version 8.6

<lang tcl>package require TclOO

namespace eval AVL {

   # Class for the overall tree; manages real public API
   oo::class create Tree {

variable root nil class constructor Template:NodeClass AVL::Node { set class [oo::class create Node [list superclass $nodeClass]]

# Create a nil instance to act as a leaf sentinel set nil [my NewNode ""] set root [$nil ref]

# Make nil be special oo::objdefine $nil { method height {} {return 0} method key {} {error "no key possible"} method value {} {error "no value possible"} method destroy {} { # Do nothing (doesn't prohibit destruction entirely) } method print {indent increment} { # Do nothing } } }

# How to actually manufacture a new node method NewNode {key} { if {![info exists nil]} {set nil ""} $class new $key $nil [list [namespace current]::my NewNode] }

# Create a new node in the tree and return it method insert {key} { set node [my NewNode $key] if {$root eq $nil} { set root $node } else { $root insert $node } return $node }

# Find the node for a particular key method lookup {key} { for {set node $root} {$node ne $nil} {} { if {[$node key] == $key} { return $node } elseif {[$node key] > $key} { set node [$node left] } else { set node [$node right] } } error "no such node" }

# Print a tree out, one node per line method print {{indent 0} {increment 1}} { $root print $indent $increment return }

   }
   # Class of an individual node; may be subclassed
   oo::class create Node {

variable key value left right 0 refcount newNode constructor {n nil instanceFactory} { set newNode $instanceFactory set 0 [expr {$nil eq "" ? [self] : $nil}] set key $n set value {} set left [set right $0] set refcount 0 } method ref {} { incr refcount return [self] } method destroy {} { if {[incr refcount -1] < 1} next } method New {key value} { set n [{*}$newNode $key] $n setValue $value return $n }

# Getters method key {} {return $key} method value {} {return $value} method left {} {return $left} method right {args} {return $right}

# Setters method setValue {newValue} { set value $newValue } method setLeft {node} { # Non-trivial because of reference management $node ref $left destroy set left $node return } method setRight {node} { # Non-trivial because of reference management $node ref $right destroy set right $node return }

# Print a node and its descendents method print {indent increment} { puts [format "%s%s => %s" [string repeat " " $indent] $key $value] incr indent $increment $left print $indent $increment $right print $indent $increment }

method height {} { return [expr {max([$left height], [$right height]) + 1}] } method balanceFactor {} { expr {[$left height] - [$right height]} }

method insert {node} { # Simple insertion if {$key > [$node key]} { if {$left eq $0} { my setLeft $node } else { $left insert $node } } else { if {$right eq $0} { my setRight $node } else { $right insert $node } }

# Rebalance this node if {[my balanceFactor] > 1} { if {[$left balanceFactor] < 0} { $left rotateLeft } my rotateRight } elseif {[my balanceFactor] < -1} { if {[$right balanceFactor] > 0} { $right rotateRight } my rotateLeft } }

# AVL Rotations method rotateLeft {} { set new [my New $key $value] set key [$right key] set value [$right value] $new setLeft $left $new setRight [$right left] my setLeft $new my setRight [$right right] }

method rotateRight {} { set new [my New $key $value] set key [$left key] set value [$left value] $new setLeft [$left right] $new setRight $right my setLeft [$left left] my setRight $new }

   }

}</lang> Demonstrating: <lang tcl># Create an AVL tree AVL::Tree create tree

  1. Populate it with some semi-random data

for {set i 33} {$i < 127} {incr i} {

   [tree insert $i] setValue \

[string repeat [format %c $i] [expr {1+int(rand()*5)}]] }

  1. Print it out

tree print

  1. Look up a few values in the tree

for {set i 0} {$i < 10} {incr i} {

   set k [expr {33+int((127-33)*rand())}]
   puts $k=>[[tree lookup $k] value]

}

  1. Destroy the tree and all its nodes

tree destroy</lang>

Output:
64 => @@@
 48 => 000
  40 => (((((
   36 => $
    34 => """
     33 => !!
     35 => #####
    38 => &&&
     37 => %
     39 => ''''
   44 => ,
    42 => **
     41 => )))
     43 => +++++
    46 => .
     45 => --
     47 => ////
  56 => 888
   52 => 444
    50 => 22222
     49 => 1111
     51 => 333
    54 => 6
     53 => 555
     55 => 77
   60 => <<<<
    58 => ::::
     57 => 99999
     59 => ;
    62 => >>>
     61 => ===
     63 => ??
 96 => ``
  80 => PPPPP
   72 => HHHH
    68 => DDD
     66 => BBBB
      65 => A
      67 => CCC
     70 => FFF
      69 => EEEE
      71 => GGG
    76 => LL
     74 => JJ
      73 => III
      75 => KKKK
     78 => N
      77 => MMMMM
      79 => OOOOO
   88 => XXX
    84 => TTTT
     82 => R
      81 => QQQQ
      83 => SSSS
     86 => V
      85 => UUU
      87 => WWW
    92 => \\\
     90 => Z
      89 => YYYYY
      91 => [
     94 => ^^^^^
      93 => ]]]]
      95 => _____
  112 => pppp
   104 => hh
    100 => d
     98 => bb
      97 => aaa
      99 => cccc
     102 => ff
      101 => eeee
      103 => gggg
    108 => lll
     106 => j
      105 => iii
      107 => kkkkk
     110 => nn
      109 => m
      111 => o
   120 => x
    116 => ttt
     114 => rrrrr
      113 => qqqqq
      115 => s
     118 => vvv
      117 => uuuu
      119 => wwww
    124 => ||||
     122 => zzzz
      121 => y
      123 => {{{
     125 => }}}}
      126 => ~~~~
53=>555
55=>77
60=><<<<
100=>d
99=>cccc
93=>]]]]
57=>99999
56=>888
47=>////
39=>''''