Reading Time: 12 minutes

[ad_1]

AVL tree is a specific type of binary search tree where the difference between heights of left and right subtrees is either 0 or 1 only for all nodes. It implements all properties of the binary search tree.

AVL tree was invented by gm Adelson – Velsky and Em Landis in 1962 and was named AVL in their honor.

Balanced binary tree

A binary tree is said to be balanced if the balance factor of each node is -1, 0, or 1. If the balance factor is any value other than these values, the tree is said to be unbalanced and needs correction.

The balance factor is the difference between the height of the right subtree and the left subtree.

Balance factor (k) = height (left(k)) – height (right(k))

  • If the balance factor is 1, the left sub-tree is one level higher than the right sub-tree.
  • If the balance factor is 0, the left sub-tree and right sub-tree contain equal height.
  • If the balance factor is -1, the left sub-tree is one level lower than the right sub-tree.

AVL tree in DS

The tree above has the properties of the binary search tree and also the balance factor for each node is either 1,0, or -1. Therefore, the above tree can be classified as an AVL tree.

Operations on AVL trees

There are 2 major operations performed on AVL trees.

  • Insertion: inserting a new node in the tree
  • Deletion: deleting an existing node in the tree

Insertion and deletion procedures in the AVL tree are exactly the same as the insertion and deletion procedures in the binary search tree article since the AVL tree is also a BST. But this insertion and deletion operation, after implementation can violate the AVL property of the balance factor.

To restore the balance factor within the range of -1 and 1, rotations are applied. A tree can be balanced by applying rotations.

AVL rotations

There are 4 types of rotations in AVL tree

1. L L rotation
2. R R rotation
3. R L rotation
4. L R rotation

L L rotation

If BST becomes unbalanced, due to a node being inserted into the left subtree of the left subtree of the root node, then we apply L L rotation. L L rotation is clockwise rotation and is applied on the edge below a node having balance factor 2.

LL Rotation in AVL

R R rotation

If BST becomes unbalanced, due to a node being inserted into the right subtree of the right subtree of the root node, then we apply R R rotation. R R rotation is counter-clockwise rotation and is applied on the edge below a node having balance factor 2.

RR Rotation in AVL

L R rotation

Double rotations are a combination of single rotations.

L R rotation = R R rotation + L L rotation

First R R rotation is performed on subtree and then L L rotation is performed on full tree.

L R rotation in AVL

R L rotation

R L rotation = L L rotation + R R rotation

First L L rotation is performed on subtree and then R R rotation is performed on full tree.

R L Rotation in AVL

Working of AVL tree

Step 1: insert 78

Insertion in AVL

Step 2: insert 36

Working of AVL tree

Step 3: insert 120

Insertion of node in AVL

Step 4: insert 100

AVL Working

Step 5: insert 110

AVL Inserting node

Step 6: insert 130

Insert node in AVL Tree

Step 7: insert 50

AVL Tree Working

Step 8: delete 120

Deletion in AVL Tree

Implementation of AVL Tree in C

#include <stdio.h>
#include <stdlib.h>

struct Node 
{
  int Val;
  struct Node *left;
  struct Node *right;
  int height;
};

int max(int a, int b);

int height(struct Node *N) 
{
  if (N == NULL)
    return 0;
  return N->height;
}

int max(int a, int b) 
{
  return (a > b) ? a : b;
}

struct Node *newNode(int Val) 
{
  struct Node *node = (struct Node *)
    malloc(sizeof(struct Node));
  node->Val = Val;
  node->left = NULL;
  node->right = NULL;
  node->height = 1;
  return (node);
}

struct Node *RotateRight(struct Node *y) 
{
  struct Node *x = y->left;
  struct Node *TEMP2 = x->right;

  x->right = y;
  y->left = TEMP2;

  y->height = max(height(y->left), height(y->right)) + 1;
  x->height = max(height(x->left), height(x->right)) + 1;

  return x;
}

struct Node *RotateLeft(struct Node *x) 
{
  struct Node *y = x->right;
  struct Node *TEMP2 = y->left;

  y->left = x;
  x->right = TEMP2;

  x->height = max(height(x->left), height(x->right)) + 1;
  y->height = max(height(y->left), height(y->right)) + 1;

  return y;
}

int getBalance(struct Node *N) 
{
  if (N == NULL)
    return 0;
  return height(N->left) - height(N->right);
}

struct Node *insertNode(struct Node *node, int Val) 
{
    
  if (node == NULL)
    return (newNode(Val));

  if (Val < node->Val)
    node->left = insertNode(node->left, Val);
  else if (Val > node->Val)
    node->right = insertNode(node->right, Val);
  else
    return node;

  node->height = 1 + max(height(node->left),height(node->right));

  int balance = getBalance(node);
  if (balance > 1 && Val < node->left->Val)
    return RotateRight(node);

  if (balance < -1 && Val > node->right->Val)
    return RotateLeft(node);

  if (balance > 1 && Val > node->left->Val) 
  {
    node->left = RotateLeft(node->left);
    return RotateRight(node);
  }

  if (balance < -1 && Val < node->right->Val) 
  {
    node->right = RotateRight(node->right);
    return RotateLeft(node);
  }

  return node;
}

struct Node *minValueNode(struct Node *node) 
{
  struct Node *current = node;

  while (current->left != NULL)
    current = current->left;

  return current;
}

struct Node *deleteNode(struct Node *root, int Val) 
{
  if (root == NULL)
    return root;

  if (Val < root->Val)
    root->left = deleteNode(root->left, Val);

  else if (Val > root->Val)
    root->right = deleteNode(root->right, Val);

  else 
  {
    if ((root->left == NULL) || (root->right == NULL)) 
    {
      struct Node *temp = root->left ? root->left : root->right;

      if (temp == NULL)
      {
        temp = root;
        root = NULL;
      } 
      else
        *root = *temp;
      free(temp);
    } 
    else 
    {
      struct Node *temp = minValueNode(root->right);

      root->Val = temp->Val;

      root->right = deleteNode(root->right, temp->Val);
    }
  }

  if (root == NULL)
    return root;

  root->height = 1 + max(height(root->left),height(root->right));

  int balance = getBalance(root);
  if (balance > 1 && getBalance(root->left) >= 0)
    return RotateRight(root);

  if (balance > 1 && getBalance(root->left) < 0) 
  {
    root->left = RotateLeft(root->left);
    return RotateRight(root);
  }

  if (balance < -1 && getBalance(root->right) <= 0)
    return RotateLeft(root);

  if (balance < -1 && getBalance(root->right) > 0) 
  {
    root->right = RotateRight(root->right);
    return RotateLeft(root);
  }

  return root;
}

void printPreOrder(struct Node *root) 
{
  if (root != NULL) 
  {
    printf("%d ", root->Val);
    printPreOrder(root->left);
    printPreOrder(root->right);
  }
}

int main() 
{
  struct Node *root = NULL;

  root = insertNode(root, 56);
  root = insertNode(root, 14);
  root = insertNode(root, 86);
  root = insertNode(root, 25);
  root = insertNode(root, 38);
  root = insertNode(root, 69);
  root = insertNode(root, 89);

  printPreOrder(root);

  root = deleteNode(root, 14);

  printf("AVL after deletion: ");
  printPreOrder(root);

  return 0;
}

AVL Tree implementation in C++

#include <iostream>
using namespace std;

struct Node 
{
  int Val;
  struct Node *left;
  struct Node *right;
  int height;
};

int max(int a, int b);

int height(struct Node *N) 
{
  if (N == NULL)
    return 0;
  return N->height;
}

int max(int a, int b) 
{
  return (a > b) ? a : b;
}

struct Node *newNode(int Val) 
{
  struct Node *node = (struct Node *)
    malloc(sizeof(struct Node));
  node->Val = Val;
  node->left = NULL;
  node->right = NULL;
  node->height = 1;
  return (node);
}

struct Node *RotateRight(struct Node *y) 
{
  struct Node *x = y->left;
  struct Node *TEMP2 = x->right;

  x->right = y;
  y->left = TEMP2;

  y->height = max(height(y->left), height(y->right)) + 1;
  x->height = max(height(x->left), height(x->right)) + 1;

  return x;
}

struct Node *RotateLeft(struct Node *x) 
{
  struct Node *y = x->right;
  struct Node *TEMP2 = y->left;

  y->left = x;
  x->right = TEMP2;

  x->height = max(height(x->left), height(x->right)) + 1;
  y->height = max(height(y->left), height(y->right)) + 1;

  return y;
}

int getBalance(struct Node *N) 
{
  if (N == NULL)
    return 0;
  return height(N->left) - height(N->right);
}

struct Node *insertNode(struct Node *node, int Val) 
{
    
  if (node == NULL)
    return (newNode(Val));

  if (Val < node->Val)
    node->left = insertNode(node->left, Val);
  else if (Val > node->Val)
    node->right = insertNode(node->right, Val);
  else
    return node;

  node->height = 1 + max(height(node->left),height(node->right));

  int balance = getBalance(node);
  if (balance > 1 && Val < node->left->Val)
    return RotateRight(node);

  if (balance < -1 && Val > node->right->Val)
    return RotateLeft(node);

  if (balance > 1 && Val > node->left->Val) 
  {
    node->left = RotateLeft(node->left);
    return RotateRight(node);
  }

  if (balance < -1 && Val < node->right->Val) 
  {
    node->right = RotateRight(node->right);
    return RotateLeft(node);
  }

  return node;
}

struct Node *minValueNode(struct Node *node) 
{
  struct Node *current = node;

  while (current->left != NULL)
    current = current->left;

  return current;
}

struct Node *deleteNode(struct Node *root, int Val) 
{
  if (root == NULL)
    return root;

  if (Val < root->Val)
    root->left = deleteNode(root->left, Val);

  else if (Val > root->Val)
    root->right = deleteNode(root->right, Val);

  else 
  {
    if ((root->left == NULL) || (root->right == NULL)) 
    {
      struct Node *temp = root->left ? root->left : root->right;

      if (temp == NULL)
      {
        temp = root;
        root = NULL;
      } 
      else
        *root = *temp;
      free(temp);
    } 
    else 
    {
      struct Node *temp = minValueNode(root->right);

      root->Val = temp->Val;

      root->right = deleteNode(root->right, temp->Val);
    }
  }

  if (root == NULL)
    return root;

  root->height = 1 + max(height(root->left),height(root->right));

  int balance = getBalance(root);
  if (balance > 1 && getBalance(root->left) >= 0)
    return RotateRight(root);

  if (balance > 1 && getBalance(root->left) < 0) 
  {
    root->left = RotateLeft(root->left);
    return RotateRight(root);
  }

  if (balance < -1 && getBalance(root->right) <= 0)
    return RotateLeft(root);

  if (balance < -1 && getBalance(root->right) > 0) 
  {
    root->right = RotateRight(root->right);
    return RotateLeft(root);
  }

  return root;
}

void printPreOrder(struct Node *root) 
{
  if (root != NULL) 
  {
    printf("%d ", root->Val);
    printPreOrder(root->left);
    printPreOrder(root->right);
  }
}

int main() 
{
  struct Node *root = NULL;

  root = insertNode(root, 56);
  root = insertNode(root, 14);
  root = insertNode(root, 86);
  root = insertNode(root, 25);
  root = insertNode(root, 38);
  root = insertNode(root, 69);
  root = insertNode(root, 89);

  printPreOrder(root);

  root = deleteNode(root, 14);

  cout <<"AVL after deletion: " ;
  printPreOrder(root);

  return 0;
}

Implementation of AVL Tree in JAVA

class Node {
  int item, height;
  Node left, right;

  Node(int d) {
    item = d;
    height = 1;
  }
}

class AVL {
  Node root;

  int height(Node N) {
    if (N == null)
      return 0;
    return N.height;
  }

  int max(int a, int b) {
    return (a > b) ? a : b;
  }

  Node RotateRight(Node y) {
    Node x = y.left;
    Node T2 = x.right;
    x.right = y;
    y.left = T2;
    y.height = max(height(y.left), height(y.right)) + 1;
    x.height = max(height(x.left), height(x.right)) + 1;
    return x;
  }

  Node RotateLeft(Node x) {
    Node y = x.right;
    Node T2 = y.left;
    y.left = x;
    x.right = T2;
    x.height = max(height(x.left), height(x.right)) + 1;
    y.height = max(height(y.left), height(y.right)) + 1;
    return y;
  }

  int getBalanceFactor(Node N) {
    if (N == null)
      return 0;
    return height(N.left) - height(N.right);
  }

  Node insertNode(Node node, int item) {

    if (node == null)
      return (new Node(item));
    if (item < node.item)
      node.left = insertNode(node.left, item);
    else if (item > node.item)
      node.right = insertNode(node.right, item);
    else
      return node;

    node.height = 1 + max(height(node.left), height(node.right));
    int balanceFactor = getBalanceFactor(node);
    if (balanceFactor > 1) {
      if (item < node.left.item) {
        return RotateRight(node);
      } else if (item > node.left.item) {
        node.left = RotateLeft(node.left);
        return RotateRight(node);
      }
    }
    if (balanceFactor < -1) {
      if (item > node.right.item) {
        return RotateLeft(node);
      } else if (item < node.right.item) {
        node.right = RotateRight(node.right);
        return RotateLeft(node);
      }
    }
    return node;
  }

  Node nodeWithMimumValue(Node node) {
    Node current = node;
    while (current.left != null)
      current = current.left;
    return current;
  }

  Node deleteNode(Node root, int item) {

    if (root == null)
      return root;
    if (item < root.item)
      root.left = deleteNode(root.left, item);
    else if (item > root.item)
      root.right = deleteNode(root.right, item);
    else {
      if ((root.left == null) || (root.right == null)) {
        Node temp = null;
        if (temp == root.left)
          temp = root.right;
        else
          temp = root.left;
        if (temp == null) {
          temp = root;
          root = null;
        } else
          root = temp;
      } else {
        Node temp = nodeWithMimumValue(root.right);
        root.item = temp.item;
        root.right = deleteNode(root.right, temp.item);
      }
    }
    if (root == null)
      return root;

    root.height = max(height(root.left), height(root.right)) + 1;
    int balanceFactor = getBalanceFactor(root);
    if (balanceFactor > 1) {
      if (getBalanceFactor(root.left) >= 0) {
        return RotateRight(root);
      } else {
        root.left = RotateLeft(root.left);
        return RotateRight(root);
      }
    }
    if (balanceFactor < -1) {
      if (getBalanceFactor(root.right) <= 0) {
        return RotateLeft(root);
      } else {
        root.right = RotateRight(root.right);
        return RotateLeft(root);
      }
    }
    return root;
  }

  void preOrder(Node node) {
    if (node != null) {
      System.out.print(node.item + " ");
      preOrder(node.left);
      preOrder(node.right);
    }
  }

  private void printTree(Node currPtr, boolean last) {
    if (currPtr != null) 
    {
      
      System.out.print(currPtr.item+ " ");
      printTree(currPtr.left, false);
      printTree(currPtr.right, true);
    }
  }

  public static void main(String[] args)
  {
    AVL tree = new AVL();
    tree.root = tree.insertNode(tree.root, 56);
    tree.root = tree.insertNode(tree.root, 14);
    tree.root = tree.insertNode(tree.root, 86);
    tree.root = tree.insertNode(tree.root, 25);
    tree.root = tree.insertNode(tree.root, 38);
    tree.root = tree.insertNode(tree.root, 69);
    tree.root = tree.insertNode(tree.root, 89);
    tree.printTree(tree.root, true);
    tree.root = tree.deleteNode(tree.root, 14);
    System.out.println("AVL After Deletion: ");
    tree.printTree(tree.root, true);
  }
}

Implementation of AVL Tree in Python

import sys
class TreeNode(object):
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.height = 1


class AVLTree(object):

    def insert_node(self, root, key):

        if not root:
            return TreeNode(key)
        elif key < root.key:
            root.left = self.insert_node(root.left, key)
        else:
            root.right = self.insert_node(root.right, key)

        root.height = 1 + max(self.getHeight(root.left),self.getHeight(root.right))

        balanceFactor = self.getBalance(root)
        if balanceFactor > 1:
            if key < root.left.key:
                return self.RotateRight(root)
            else:
                root.left = self.RotateLeft(root.left)
                return self.RotateRight(root)

        if balanceFactor < -1:
            if key > root.right.key:
                return self.RotateLeft(root)
            else:
                root.right = self.RotateRight(root.right)
                return self.RotateLeft(root)

        return root

    def delete_node(self, root, key):

        if not root:
            return root
        elif key < root.key:
            root.left = self.delete_node(root.left, key)
        elif key > root.key:
            root.right = self.delete_node(root.right, key)
        else:
            if root.left is None:
                temp = root.right
                root = None
                return temp
            elif root.right is None:
                temp = root.left
                root = None
                return temp
            temp = self.getMinValueNode(root.right)
            root.key = temp.key
            root.right = self.delete_node(root.right,
                                          temp.key)
        if root is None:
            return root

        root.height = 1 + max(self.getHeight(root.left),
                              self.getHeight(root.right))

        balanceFactor = self.getBalance(root)

        if balanceFactor > 1:
            if self.getBalance(root.left) >= 0:
                return self.RotateRight(root)
            else:
                root.left = self.RotateLeft(root.left)
                return self.RotateRight(root)
        if balanceFactor < -1:
            if self.getBalance(root.right) <= 0:
                return self.RotateLeft(root)
            else:
                root.right = self.RotateRight(root.right)
                return self.RotateLeft(root)
        return root

    def RotateLeft(self, z):
        y = z.right
        T2 = y.left
        y.left = z
        z.right = T2
        z.height = 1 + max(self.getHeight(z.left),self.getHeight(z.right))
        y.height = 1 + max(self.getHeight(y.left),self.getHeight(y.right))
        return y

    def RotateRight(self, z):
        y = z.left
        T3 = y.right
        y.right = z
        z.left = T3
        z.height = 1 + max(self.getHeight(z.left),self.getHeight(z.right))
        y.height = 1 + max(self.getHeight(y.left),self.getHeight(y.right))
        return y

    def getHeight(self, root):
        if not root:
            return 0
        return root.height

    def getBalance(self, root):
        if not root:
            return 0
        return self.getHeight(root.left) - self.getHeight(root.right)

    def getMinValueNode(self, root):
        if root is None or root.left is None:
            return root
        return self.getMinValueNode(root.left)

    def preOrder(self, root):
        if not root:
            return
        print("{0} ".format(root.key), end="")
        self.preOrder(root.left)
        self.preOrder(root.right)

    def printAVL(self, currPtr, last):
        if currPtr != None:
            
            print(currPtr.key)
            self.printAVL(currPtr.left, False)
            self.printAVL(currPtr.right, True)


myTree = AVLTree()
root = None
nums = [56, 14, 86, 25, 38, 69, 89]
for num in nums:
    root = myTree.insert_node(root, num)
myTree.printAVL(root, True)
key = 14
root = myTree.delete_node(root, key)
print("After Deletion: ")
myTree.printAVL(root, True)

Complexity of AVL tree

Insertion: O( log n )
Deletion: O( log n )
Search: O( log n )

Applications of AVL Tree

  • Searching operations in very large datasets
  • Indexing of data in very large databases.

Conclusion

AVL Trees are self-balancing binary trees. If at any point, during insertion or deletion, there is an unbalancing in the tree, it is again balanced by different rotations. AVL Trees are more balanced than red-black trees. AVL Tree is preferred over red-black trees in cases where the insertion and deletion are less frequent.

In further articles, we will learn about another type of binary tree known as spanning tree.


[ad_2]

Source link

Spread the Word!