We have discussed Insertion of AVL Tree. In this post, we will follow a similar approach for deletion.
Steps to follow for deletion.Â
To make sure that the given tree remains AVL after every deletion, we must augment the standard BST delete operation to perform some re-balancing. Following are two basic operations that can be performed to re-balance a BST without violating the BST property (keys(left) < key(root) < keys(right)).Â
- Left Rotation
- Right Rotation

Example:Â Â
#include <bits/stdc++.h>
using namespace std;
// An AVL tree node
class Node {
public:
int key;
Node *left;
Node *right;
int height;
Node(int k) {
key = k;
left = nullptr;
right = nullptr;
height = 1;
}
};
// A utility function to get the height
// of the tree
int height(Node *N) {
if (N == nullptr)
return 0;
return N->height;
}
// A utility function to right rotate
// subtree rooted with y
Node *rightRotate(Node *y) {
Node *x = y->left;
Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = 1 + max(height(y->left), height(y->right));
// Fixed line below:
x->height = 1 + max(height(x->left), height(x->right));
// Return new root
return x;
}
// A utility function to left rotate
// subtree rooted with x
Node *leftRotate(Node *x) {
Node *y = x->right;
Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = 1 + max(height(x->left),
height(x->right));
y->height = 1 + max(height(y->left),
height(y->right));
// Return new root
return y;
}
// Get Balance factor of node N
int getBalance(Node *N) {
if (N == nullptr)
return 0;
return height(N->left) -
height(N->right);
}
Node* insert(Node* node, int key) {
// 1. Perform the normal BST rotation
if (node == nullptr)
return new Node(key);
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys not allowed
return node;
// 2. Update height of this ancestor node
node->height = 1 + max(height(node->left),
height(node->right));
// 3. Get the balance factor of this
// ancestor node to check whether this
// node became unbalanced
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
// return the (unchanged) node pointer
return node;
}
// Given a non-empty binary search tree,
// return the node with minimum key value
// found in that tree. Note that the entire
// tree does not need to be searched.
Node * minValueNode(Node* node) {
Node* current = node;
// loop down to find the leftmost leaf
while (current->left != nullptr)
current = current->left;
return current;
}
// Recursive function to delete a node with
// given key from subtree with given root.
// It returns root of the modified subtree.
Node* deleteNode(Node* root, int key) {
// STEP 1: PERFORM STANDARD BST DELETE
if (root == nullptr)
return root;
// If the key to be deleted is smaller
// than the root's key, then it lies in
// left subtree
if (key < root->key)
root->left = deleteNode(root->left, key);
// If the key to be deleted is greater
// than the root's key, then it lies in
// right subtree
else if (key > root->key)
root->right = deleteNode(root->right, key);
// if key is same as root's key, then
// this is the node to be deleted
else {
// node with only one child or no child
if ((root->left == nullptr) ||
(root->right == nullptr)) {
Node *temp = root->left ?
root->left : root->right;
// No child case
if (temp == nullptr) {
temp = root;
root = nullptr;
} else // One child case
Node *temp = root->left ? root->left : root->right;
delete root; // delete the current node
return temp; // return the child to be linked to the parent
} else {
// node with two children: Get the
// inorder successor (smallest in
// the right subtree)
Node* temp = minValueNode(root->right);
// Copy the inorder successor's
// data to this node
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
}
// If the tree had only one node then return
if (root == nullptr)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root->height = 1 + max(height(root->left),
height(root->right));
// STEP 3: GET THE BALANCE FACTOR OF THIS
// NODE (to check whether this node
// became unbalanced)
int balance = getBalance(root);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 &&
getBalance(root->left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 &&
getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
// Right Right Case
if (balance < -1 &&
getBalance(root->right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 &&
getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
// A utility function to print preorder
// traversal of the tree.
void preOrder(Node *root) {
if (root != nullptr) {
cout << root->key << " ";
preOrder(root->left);
preOrder(root->right);
}
}
// Driver Code
int main() {
Node *root = nullptr;
// Constructing tree given in the
// above figure
root = insert(root, 9);
root = insert(root, 5);
root = insert(root, 10);
root = insert(root, 0);
root = insert(root, 6);
root = insert(root, 11);
root = insert(root, -1);
root = insert(root, 1);
root = insert(root, 2);
cout << "Preorder traversal of the "
"constructed AVL tree is \n";
preOrder(root);
root = deleteNode(root, 10);
cout << "\nPreorder traversal after"
" deletion of 10 \n";
preOrder(root);
return 0;
}
import java.util.ArrayList;
import java.util.List;
// An AVL tree node
class Node {
public int key;
public Node left;
public Node right;
public int height;
public Node(int k) {
key = k;
left = null;
right = null;
height = 1;
}
}
public class AVLTree {
// A utility function to get the height of the tree
private int height(Node N) {
if (N == null)
return 0;
return N.height;
}
// A utility function to right rotate subtree rooted with y
private Node rightRotate(Node y) {
Node x = y.left;
Node T2 = x.right;
// Perform rotation
x.right = y;
y.left = T2;
// Update heights
y.height = 1 + Math.max(height(y.left), height(y.right));
x.height = 1 + Math.max(height(x.left), height(x.right));
// Return new root
return x;
}
// A utility function to left rotate subtree rooted with x
private Node leftRotate(Node x) {
Node y = x.right;
Node T2 = y.left;
// Perform rotation
y.left = x;
x.right = T2;
// Update heights
x.height = 1 + Math.max(height(x.left), height(x.right));
y.height = 1 + Math.max(height(y.left), height(y.right));
// Return new root
return y;
}
// Get Balance factor of node N
private int getBalance(Node N) {
if (N == null)
return 0;
return height(N.left) - height(N.right);
}
public Node insert(Node node, int key) {
// 1. Perform the normal BST rotation
if (node == null)
return new Node(key);
if (key < node.key)
node.left = insert(node.left, key);
else if (key > node.key)
node.right = insert(node.right, key);
else // Equal keys not allowed
return node;
// 2. Update height of this ancestor node
node.height = 1 + Math.max(height(node.left), height(node.right));
// 3. Get the balance factor of this ancestor node to check whether this node became unbalanced
int balance = getBalance(node);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && key < node.left.key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node.right.key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node.left.key) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node.right.key) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
// return the (unchanged) node pointer
return node;
}
// Given a non-empty binary search tree, return the node with minimum key value found in that tree. Note that the entire tree does not need to be searched.
private Node minValueNode(Node node) {
Node current = node;
// loop down to find the leftmost leaf
while (current.left!= null)
current = current.left;
return current;
}
// Recursive function to delete a node with given key from subtree with given root. It returns root of the modified subtree.
public Node deleteNode(Node root, int key) {
// STEP 1: PERFORM STANDARD BST DELETE
if (root == null)
return root;
// If the key to be deleted is smaller than the root's key, then it lies in left subtree
if (key < root.key)
root.left = deleteNode(root.left, key);
// If the key to be deleted is greater than the root's key, then it lies in right subtree
else if (key > root.key)
root.right = deleteNode(root.right, key);
// if key is same as root's key, then this is the node to be deleted
else {
// node with only one child or no child
if ((root.left == null) || (root.right == null)) {
Node temp = root.left!= null? root.left : root.right;
// No child case
if (temp == null) {
temp = root;
root = null;
} else // One child case
return temp;
} else {
// node with two children: Get the inorder successor (smallest in the right subtree)
Node temp = minValueNode(root.right);
// Copy the inorder successor's data to this node
root.key = temp.key;
// Delete the inorder successor
root.right = deleteNode(root.right, temp.key);
}
}
// If the tree had only one node then return
if (root == null)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root.height = 1 + Math.max(height(root.left), height(root.right));
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this node became unbalanced)
int balance = getBalance(root);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && getBalance(root.left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 && getBalance(root.left) < 0) {
root.left = leftRotate(root.left);
return rightRotate(root);
}
// Right Right Case
if (balance < -1 && getBalance(root.right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 && getBalance(root.right) > 0) {
root.right = rightRotate(root.right);
return leftRotate(root);
}
return root;
}
// A utility function to print preorder traversal of the tree.
private void preOrder(Node root) {
if (root!= null) {
System.out.print(root.key + " ");
preOrder(root.left);
preOrder(root.right);
}
}
// Driver Code
public static void main(String[] args) {
AVLTree tree = new AVLTree();
Node root = null;
// Constructing tree given in the above figure
root = tree.insert(root, 9);
root = tree.insert(root, 5);
root = tree.insert(root, 10);
root = tree.insert(root, 0);
root = tree.insert(root, 6);
root = tree.insert(root, 11);
root = tree.insert(root, -1);
root = tree.insert(root, 1);
root = tree.insert(root, 2);
System.out.println("Preorder traversal of the constructed AVL tree is");
tree.preOrder(root);
root = tree.deleteNode(root, 10);
System.out.println("\nPreorder traversal after deletion of 10");
tree.preOrder(root);
}
}
import math
# An AVL tree node
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
self.height = 1
class AVLTree:
# A utility function to get the height of the tree
def height(self, N):
if not N:
return 0
return N.height
# A utility function to right rotate subtree rooted with y
def rightRotate(self, y):
x = y.left
T2 = x.right
# Perform rotation
x.right = y
y.left = T2
# Update heights
y.height = 1 + max(self.height(y.left), self.height(y.right))
x.height = 1 + max(self.height(x.left), self.height(x.right))
# Return new root
return x
# A utility function to left rotate subtree rooted with x
def leftRotate(self, x):
y = x.right
T2 = y.left
# Perform rotation
y.left = x
x.right = T2
# Update heights
x.height = 1 + max(self.height(x.left), self.height(x.right))
y.height = 1 + max(self.height(y.left), self.height(y.right))
# Return new root
return y
# Get Balance factor of node N
def getBalance(self, N):
if not N:
return 0
return self.height(N.left) - self.height(N.right)
def insert(self, node, key):
# 1. Perform the normal BST rotation
if not node:
return Node(key)
if key < node.key:
node.left = self.insert(node.left, key)
elif key > node.key:
node.right = self.insert(node.right, key)
else: # Equal keys not allowed
return node
# 2. Update height of this ancestor node
node.height = 1 + max(self.height(node.left), self.height(node.right))
# 3. Get the balance factor of this ancestor node to check whether this node became unbalanced
balance = self.getBalance(node)
# If this node becomes unbalanced, then there are 4 cases
# Left Left Case
if balance > 1 and key < node.left.key:
return self.rightRotate(node)
# Right Right Case
if balance < -1 and key > node.right.key:
return self.leftRotate(node)
# Left Right Case
if balance > 1 and key > node.left.key:
node.left = self.leftRotate(node.left)
return self.rightRotate(node)
# Right Left Case
if balance < -1 and key < node.right.key:
node.right = self.rightRotate(node.right)
return self.leftRotate(node)
# return the (unchanged) node pointer
return node
# Given a non-empty binary search tree, return the node with minimum key value found in that tree. Note that the entire tree does not need to be searched.
def minValueNode(self, node):
current = node
# loop down to find the leftmost leaf
while current.left is not None:
current = current.left
return current
# Recursive function to delete a node with given key from subtree with given root. It returns root of the modified subtree.
def deleteNode(self, root, key):
# STEP 1: PERFORM STANDARD BST DELETE
if not root:
return root
# If the key to be deleted is smaller than the root's key, then it lies in left subtree
if key < root.key:
root.left = self.deleteNode(root.left, key)
# If the key to be deleted is greater than the root's key, then it lies in right subtree
elif key > root.key:
root.right = self.deleteNode(root.right, key)
# if key is same as root's key, then this is the node to be deleted
else:
# node with only one child or no child
if root.left is None or root.right is None:
temp = root.left if root.left is not None else root.right
if temp is None:
temp = root
root = None
else: # One child case
root = temp
else:
# node with two children: Get the inorder successor (smallest in the right subtree)
temp = self.minValueNode(root.right)
# Copy the inorder successor's data to this node
root.key = temp.key
# Delete the inorder successor
root.right = self.deleteNode(root.right, temp.key)
if root is None:
return root
# STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root.height = 1 + max(self.height(root.left), self.height(root.right))
# STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this node became unbalanced)
balance = self.getBalance(root)
# If this node becomes unbalanced, then there are 4 cases
# Left Left Case
if balance > 1 and self.getBalance(root.left) >= 0:
return self.rightRotate(root)
# Left Right Case
if balance > 1 and self.getBalance(root.left) < 0:
root.left = self.leftRotate(root.left)
return self.rightRotate(root)
# Right Right Case
if balance < -1 and self.getBalance(root.right) <= 0:
return self.leftRotate(root)
# Right Left Case
if balance < -1 and self.getBalance(root.right) > 0:
root.right = self.rightRotate(root.right)
return self.leftRotate(root)
return root
# A utility function to print preorder traversal of the tree.
def preOrder(self, root):
if root:
print("{}".format(root.key), end=" ")
self.preOrder(root.left)
self.preOrder(root.right)
# Driver Code
if __name__ == '__main__':
tree = AVLTree()
root = None
# Constructing tree given in the above figure
root = tree.insert(root, 9)
root = tree.insert(root, 5)
root = tree.insert(root, 10)
root = tree.insert(root, 0)
root = tree.insert(root, 6)
root = tree.insert(root, 11)
root = tree.insert(root, -1)
root = tree.insert(root, 1)
root = tree.insert(root, 2)
print("Preorder traversal of the constructed AVL tree is")
tree.preOrder(root)
root = tree.deleteNode(root, 10)
print("\nPreorder traversal after deletion of 10")
tree.preOrder(root)
using System;
// An AVL tree node
public class Node
{
public int key;
public Node left, right;
public int height;
public Node(int item)
{
key = item;
left = right = null;
height = 1;
}
}
public class AVLTree
{
// A utility function to get the height of the tree
public int height(Node N)
{
if (N == null)
return 0;
return N.height;
}
// A utility function to right rotate subtree rooted with y
public Node rightRotate(Node y)
{
Node x = y.left;
Node T2 = x.right;
// Perform rotation
x.right = y;
y.left = T2;
// Update heights
y.height = Math.Max(height(y.left), height(y.right)) + 1;
x.height = Math.Max(height(x.left), height(x.right)) + 1;
// Return new root
return x;
}
// A utility function to left rotate subtree rooted with x
public Node leftRotate(Node x)
{
Node y = x.right;
Node T2 = y.left;
// Perform rotation
y.left = x;
x.right = T2;
// Update heights
x.height = Math.Max(height(x.left), height(x.right)) + 1;
y.height = Math.Max(height(y.left), height(y.right)) + 1;
// Return new root
return y;
}
// Get Balance factor of node N
public int getBalance(Node N)
{
if (N == null)
return 0;
return height(N.left) - height(N.right);
}
public Node insert(Node node, int key)
{
// 1. Perform the normal BST rotation
if (node == null)
return (new Node(key));
if (key < node.key)
node.left = insert(node.left, key);
else if (key > node.key)
node.right = insert(node.right, key);
else // Equal keys not allowed
return node;
// 2. Update height of this ancestor node
node.height = 1 + Math.Max(height(node.left), height(node.right));
// 3. Get the balance factor of this ancestor node to check whether this node became unbalanced
int balance = getBalance(node);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && key < node.left.key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node.right.key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node.left.key)
{
node.left = leftRotate(node.left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node.right.key)
{
node.right = rightRotate(node.right);
return leftRotate(node);
}
// return the (unchanged) node pointer
return node;
}
// Given a non-empty binary search tree, return the node with minimum key value found in that tree. Note that the entire tree does not need to be searched.
public Node minValueNode(Node node)
{
Node current = node;
// loop down to find the leftmost leaf
while (current.left!= null)
current = current.left;
return current;
}
// Recursive function to delete a node with given key from subtree with given root. It returns root of the modified subtree.
public Node deleteNode(Node root, int key)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == null)
return root;
// If the key to be deleted is smaller than the root's key, then it lies in left subtree
if (key < root.key)
root.left = deleteNode(root.left, key);
// If the key to be deleted is greater than the root's key, then it lies in right subtree
else if (key > root.key)
root.right = deleteNode(root.right, key);
// if key is same as root's key, then this is the node to be deleted
else
{
// node with only one child or no child
if ((root.left == null) || (root.right == null))
{
Node temp = root.left!= null ? root.left : root.right;
// No child case
if (temp == null)
{
temp = root;
root = null;
}
else // One child case
root = temp; // Copy the contents of the non-empty child
}
else
{
// node with two children: Get the inorder successor (smallest in the right subtree)
Node temp = minValueNode(root.right);
// Copy the inorder successor's data to this node
root.key = temp.key;
// Delete the inorder successor
root.right = deleteNode(root.right, temp.key);
}
}
if (root == null)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root.height = Math.Max(height(root.left), height(root.right)) + 1;
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this node became unbalanced)
int balance = getBalance(root);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && getBalance(root.left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 && getBalance(root.left) < 0)
{
root.left = leftRotate(root.left);
return rightRotate(root);
}
// Right Right Case
if (balance < -1 && getBalance(root.right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 && getBalance(root.right) > 0)
{
root.right = rightRotate(root.right);
return leftRotate(root);
}
return root;
}
// A utility function to print preorder traversal of the tree.
public void preOrder(Node root)
{
if (root!= null)
{
Console.Write(root.key + " ");
preOrder(root.left);
preOrder(root.right);
}
}
// Driver Code
public static void Main(string[] args)
{
AVLTree tree = new AVLTree();
Node root = null;
// Constructing tree given in the above figure
root = tree.insert(root, 9);
root = tree.insert(root, 5);
root = tree.insert(root, 10);
root = tree.insert(root, 0);
root = tree.insert(root, 6);
root = tree.insert(root, 11);
root = tree.insert(root, -1);
root = tree.insert(root, 1);
root = tree.insert(root, 2);
Console.WriteLine("Preorder traversal of the constructed AVL tree is");
tree.preOrder(root);
root = tree.deleteNode(root, 10);
Console.WriteLine("\nPreorder traversal after deletion of 10");
tree.preOrder(root);
}
}
'use strict';
// An AVL tree node
class Node {
constructor(item) {
this.key = item;
this.left = null;
this.right = null;
this.height = 1;
}
}
class AVLTree {
// A utility function to get the height of the tree
height(N) {
if (N === null)
return 0;
return N.height;
}
// A utility function to right rotate subtree rooted with y
rightRotate(y) {
let x = y.left;
let T2 = x.right;
// Perform rotation
x.right = y;
y.left = T2;
// Update heights
y.height = Math.max(this.height(y.left), this.height(y.right)) + 1;
x.height = Math.max(this.height(x.left), this.height(x.right)) + 1;
// Return new root
return x;
}
// A utility function to left rotate subtree rooted with x
leftRotate(x) {
let y = x.right;
let T2 = y.left;
// Perform rotation
y.left = x;
x.right = T2;
// Update heights
x.height = Math.max(this.height(x.left), this.height(x.right)) + 1;
y.height = Math.max(this.height(y.left), this.height(y.right)) + 1;
// Return new root
return y;
}
// Get Balance factor of node N
getBalance(N) {
if (N === null)
return 0;
return this.height(N.left) - this.height(N.right);
}
insert(node, key) {
// 1. Perform the normal BST rotation
if (node === null)
return new Node(key);
if (key < node.key)
node.left = this.insert(node.left, key);
else if (key > node.key)
node.right = this.insert(node.right, key);
else // Equal keys not allowed
return node;
// 2. Update height of this ancestor node
node.height = 1 + Math.max(this.height(node.left), this.height(node.right));
// 3. Get the balance factor of this ancestor node to check whether this node became unbalanced
let balance = this.getBalance(node);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && key < node.left.key)
return this.rightRotate(node);
// Right Right Case
if (balance < -1 && key > node.right.key)
return this.leftRotate(node);
// Left Right Case
if (balance > 1 && key > node.left.key) {
node.left = this.leftRotate(node.left);
return this.rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node.right.key) {
node.right = this.rightRotate(node.right);
return this.leftRotate(node);
}
// return the (unchanged) node pointer
return node;
}
// Given a non-empty binary search tree, return the node with minimum key value found in that tree. Note that the entire tree does not need to be searched.
minValueNode(node) {
let current = node;
// loop down to find the leftmost leaf
while (current.left!== null)
current = current.left;
return current;
}
// Recursive function to delete a node with given key from subtree with given root. It returns root of the modified subtree.
deleteNode(root, key) {
// STEP 1: PERFORM STANDARD BST DELETE
if (root === null)
return root;
// If the key to be deleted is smaller than the root's key, then it lies in left subtree
if (key < root.key)
root.left = this.deleteNode(root.left, key);
// If the key to be deleted is greater than the root's key, then it lies in right subtree
else if (key > root.key)
root.right = this.deleteNode(root.right, key);
// if key is same as root's key, then this is the node to be deleted
else {
// node with only one child or no child
if ((root.left === null) || (root.right === null)) {
let temp = root.left!== null? root.left : root.right;
// No child case
if (temp === null) {
temp = root;
root = null;
} else // One child case
root = temp; // Copy the contents of the non-empty child
} else {
// node with two children: Get the inorder successor (smallest in the right subtree)
let temp = this.minValueNode(root.right);
// Copy the inorder successor's data to this node
root.key = temp.key;
// Delete the inorder successor
root.right = this.deleteNode(root.right, temp.key);
}
}
if (root === null)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
root.height = Math.max(this.height(root.left), this.height(root.right)) + 1;
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this node became unbalanced)
let balance = this.getBalance(root);
// If this node becomes unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && this.getBalance(root.left) >= 0)
return this.rightRotate(root);
// Left Right Case
if (balance > 1 && this.getBalance(root.left) < 0) {
root.left = this.leftRotate(root.left);
return this.rightRotate(root);
}
// Right Right Case
if (balance < -1 && this.getBalance(root.right) <= 0)
return this.leftRotate(root);
// Right Left Case
if (balance < -1 && this.getBalance(root.right) > 0) {
root.right = this.rightRotate(root.right);
return this.leftRotate(root);
}
return root;
}
// A utility function to print preorder traversal of the tree.
preOrder(root) {
if (root!== null) {
console.log(root.key + " ");
this.preOrder(root.left);
this.preOrder(root.right);
}
}
}
// Driver Code
let tree = new AVLTree();
let root = null;
// Constructing tree given in the above figure
root = tree.insert(root, 9);
root = tree.insert(root, 5);
root = tree.insert(root, 10);
root = tree.insert(root, 0);
root = tree.insert(root, 6);
root = tree.insert(root, 11);
root = tree.insert(root, -1);
root = tree.insert(root, 1);
root = tree.insert(root, 2);
console.log("Preorder traversal of the constructed AVL tree is");
tree.preOrder(root);
root = tree.deleteNode(root, 10);
console.log("\nPreorder traversal after deletion of 10");
tree.preOrder(root);
Output
Preorder traversal of the constructed AVL tree is 9 1 0 -1 5 2 6 10 11 Preorder traversal after deletion of 10 1 0 -1 9 5 2 6 11
Time Complexity: The rotation operations (left and right rotate) take constant time as only few pointers are being changed there. Updating the height and getting the balance factor also take constant time. So the time complexity of AVL delete remains same as BST delete which is O(h) where h is height of the tree. Since AVL tree is balanced, the height is O(log n). So time complexity of AVL delete is O(log n).Â
Auxiliary Space: O(log n) for recursion call stack as we have written a recursive method to delete
Summary of Deletion in AVL Trees:
- Deletion in AVL trees is similar to deletion in a Binary Search Tree (BST), but followed by rebalancing operations.
- After deleting a node, the balance factor of ancestor nodes may change.
- If the balance factor goes outside the range of -1 to +1, rotations (LL, RR, LR, RL) are required to restore balance.
- The type of rotation depends on the balance factors of the affected node and its children.
- Time complexity of deletion remains O(log n) due to the balanced nature of the tree.