Insertion, Searching and Deletion in AVL trees containing a parent node pointer
Last Updated :
21 May, 2024
AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. The insertion and deletion in AVL trees have been discussed in the previous article. In this article, insert, search, and delete operations are discussed on AVL trees that also have a parent pointer in their structure.
Definition of AVL tree node:
C++
struct AVLwithparent {
// Pointer to the left and the
// right subtree
struct AVLwithparent* left;
struct AVLwithparent* right;
// Stores the data in the node
int key;
// Stores the parent pointer
struct AVLwithparent* par;
// Stores the height of the
// current tree
int height;
}
Java
class AVLwithParent {
// Pointer to the left and the right subtree
AVLwithParent left;
AVLwithParent right;
// Stores the data in the node
int key;
// Stores the parent pointer
AVLwithParent par;
// Stores the height of the current tree
int height;
}
Python
# Python code
class AVLwithParent:
def __init__(self):
# Pointer to the left and the right subtree
self.left = None
self.right = None
# Stores the data in the node
self.key = None
# Stores the parent pointer
self.par = None
# Stores the height of the current tree
self.height = None
# This code is contributed by princekumaras
C#
class AVLwithParent
{
// Pointer to the left and the right subtree
public AVLwithParent left;
public AVLwithParent right;
// Stores the data in the node
public int key;
// Stores the parent pointer
public AVLwithParent par;
// Stores the height of the current tree
public int height;
}
JavaScript
class AVLwithParent {
constructor() {
// Pointer to the left and the right subtree
this.left = null;
this.right = null;
// Stores the data in the node
this.key = null;
// Stores the parent pointer
this.par = null;
// Stores the height of the current tree
this.height = null;
}
}
Representation of the Node:

Below is the example of an AVL tree containing a parent pointer:

Insert Operation: The insertion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the parent pointers need to be updated with every insertion and rotation accordingly. Follow the steps below to perform insert operation:
- Perform standard BST insert for the node to be placed at its correct position.
- Increase the height of each node encountered by 1 while finding the correct position for the node to be inserted.
- Update the parent and child pointers of the inserted node and its parent respectively.
- Starting from the inserted node till the root node check if the AVL condition is satisfied for each node on this path.
- If w is the node where the AVL condition is not satisfied then we have 4 cases:
- Left Left Case: (If the left subtree of the left child of w has the inserted node)
- Left Right Case: (If the right subtree of the left child of w has the inserted node)
- Right Left Case: (If the left subtree of the right child of w has the inserted node)
- Right Right Case: (If the right subtree of the right child of w has the inserted node)
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of the
// left child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of
// the tmpnode
tmpnode->par = root->par;
// Update the parent pointer
// of the root
root->par = tmpnode;
// Update tmpnode as the left or the
// right child of its parent pointer
// according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the
// right child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of
// the tmpnode
tmpnode->par = root->par;
// Update the parent pointer
// of the root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
// If the root is NULL
if (root == NULL) {
cout << "Error in memory"
<< endl;
}
// Otherwise
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight
= root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is already
// in the tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(
struct AVLwithparent* root)
{
// Print the node's value along
// with its parent value
cout << "Node: " << root->key
<< ", Parent Node: ";
if (root->par != NULL)
cout << root->par->key << endl;
else
cout << "NULL" << endl;
// Recur to the left subtree
if (root->left != NULL) {
printpreorder(root->left);
}
// Recur to the right subtree
if (root->right != NULL) {
printpreorder(root->right);
}
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function Call to insert nodes
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 20);
root = Insert(root, NULL, 30);
root = Insert(root, NULL, 40);
root = Insert(root, NULL, 50);
root = Insert(root, NULL, 25);
// Function call to print the tree
printpreorder(root);
}
Java
class AVLwithparent {
int key;
AVLwithparent left;
AVLwithparent right;
AVLwithparent par;
int height;
public AVLwithparent(int key) {
this.key = key;
this.left = null;
this.right = null;
this.par = null;
this.height = 1;
}
}
public class AVLTreeWithParent {
// Function to update the height of a node based on its children's heights
public static void updateHeight(AVLwithparent root) {
if (root != null) {
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
root.height = Math.max(leftHeight, rightHeight) + 1;
}
}
// Left-Left Rotation (LLR) to balance the AVL tree
public static AVLwithparent LLR(AVLwithparent root) {
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null) {
tmpnode.right.par = root;
}
tmpnode.right = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par != null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Right-Right Rotation (RRR) to balance the AVL tree
public static AVLwithparent RRR(AVLwithparent root) {
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null) {
tmpnode.left.par = root;
}
tmpnode.left = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par != null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Left-Right Rotation (LRR) to balance the AVL tree
public static AVLwithparent LRR(AVLwithparent root) {
root.left = RRR(root.left);
return LLR(root);
}
// Right-Left Rotation (RLR) to balance the AVL tree
public static AVLwithparent RLR(AVLwithparent root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a key into the AVL tree and balance the tree if needed
public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
root = new AVLwithparent(key);
root.par = parent;
} else if (root.key > key) {
root.left = insert(root.left, root, key);
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) == 2) {
if (key < root.left.key) {
root = LLR(root);
} else {
root = LRR(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) == 2) {
if (key < root.right.key) {
root = RLR(root);
} else {
root = RRR(root);
}
}
}
updateHeight(root);
return root;
}
// Function to print the nodes of the AVL tree in preorder
public static void printPreorder(AVLwithparent root) {
if (root != null) {
String parentKey = (root.par != null) ? Integer.toString(root.par.key) : "NULL";
System.out.println("Node: " + root.key + ", Parent Node: " + parentKey);
printPreorder(root.left);
printPreorder(root.right);
}
}
public static void main(String[] args) {
AVLwithparent root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
printPreorder(root);
}
}
Python
class AVLwithparent:
def __init__(self, key):
# Initialize a node with key, left and right child, parent, and height.
self.left = None
self.right = None
self.key = key
self.par = None
self.height = 1
# Function to update the height of a node based on its children's heights
def update_height(root):
if root is not None:
left_height = root.left.height if root.left else 0 # Get the height of the left child
right_height = root.right.height if root.right else 0 # Get the height of the right child
root.height = max(left_height, right_height) + 1 # Update the height of the current node
# Left-Left Rotation (LLR) to balance the AVL tree
def LLR(root):
# Perform a left rotation and then a right rotation
# to balance the tree when there's an imbalance in the left subtree
tmpnode = root.left
root.left = tmpnode.right
if tmpnode.right:
tmpnode.right.par = root
tmpnode.right = root
tmpnode.par = root.par
root.par = tmpnode
if tmpnode.par:
if root.key < tmpnode.par.key:
tmpnode.par.left = tmpnode
else:
tmpnode.par.right = tmpnode
update_height(root)
update_height(tmpnode)
return tmpnode
# Right-Right Rotation (RRR) to balance the AVL tree
def RRR(root):
# Perform a right rotation and then a left rotation
# to balance the tree when there's an imbalance in the right subtree
tmpnode = root.right
root.right = tmpnode.left
if tmpnode.left:
tmpnode.left.par = root
tmpnode.left = root
tmpnode.par = root.par
root.par = tmpnode
if tmpnode.par:
if root.key < tmpnode.par.key:
tmpnode.par.left = tmpnode
else:
tmpnode.par.right = tmpnode
update_height(root)
update_height(tmpnode)
return tmpnode
# Left-Right Rotation (LRR) to balance the AVL tree
def LRR(root):
# Perform a right rotation on the left child and then a left rotation on the root
root.left = RRR(root.left)
return LLR(root)
# Right-Left Rotation (RLR) to balance the AVL tree
def RLR(root):
# Perform a left rotation on the right child and then a right rotation on the root
root.right = LLR(root.right)
return RRR(root)
# Function to insert a key into the AVL tree and balance the tree if needed
def insert(root, parent, key):
if root is None:
root = AVLwithparent(key) # Create a new node if the current node is None
root.par = parent # Set the parent of the new node
elif root.key > key:
# Insert the key into the left subtree and balance the tree if needed
root.left = insert(root.left, root, key)
left_height = root.left.height if root.left else 0
right_height = root.right.height if root.right else 0
if abs(left_height - right_height) == 2:
if key < root.left.key:
root = LLR(root)
else:
root = LRR(root)
elif root.key < key:
# Insert the key into the right subtree and balance the tree if needed
root.right = insert(root.right, root, key)
left_height = root.left.height if root.left else 0
right_height = root.right.height if root.right else 0
if abs(left_height - right_height) == 2:
if key < root.right.key:
root = RLR(root)
else:
root = RRR(root)
update_height(root) # Update the height of the current node after insertion
return root # Return the root of the updated subtree
# Function to print the nodes of the AVL tree in preorder
def print_preorder(root):
if root:
parent_key = root.par.key if root.par else "NULL" # Get the key of the parent node or "NULL" if it's None
print(f"Node: {root.key}, Parent Node: {parent_key}") # Print the node and its parent
print_preorder(root.left) # Print the left subtree in preorder
print_preorder(root.right) # Print the right subtree in preorder
# Main function to demonstrate AVL tree operations
if __name__ == "__main__":
root = None # Initialize the root of the AVL tree as None
# Insert keys into the AVL tree
root = insert(root, None, 10)
root = insert(root, None, 20)
root = insert(root, None, 30)
root = insert(root, None, 40)
root = insert(root, None, 50)
root = insert(root, None, 25)
# Print the AVL tree in preorder
print_preorder(root)
C#
using System;
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public int key;
public AVLwithparent par;
public int height;
}
public class Program
{
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
root.height = val;
}
}
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpNode = root.left;
root.left = tmpNode.right;
if (tmpNode.right != null)
tmpNode.right.par = root;
tmpNode.right = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par != null && root.key < tmpNode.par.key)
{
tmpNode.par.left = tmpNode;
}
else
{
if (tmpNode.par != null)
tmpNode.par.right = tmpNode;
}
root = tmpNode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpNode = root.right;
root.right = tmpNode.left;
if (tmpNode.left != null)
tmpNode.left.par = root;
tmpNode.left = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par != null && root.key < tmpNode.par.key)
{
tmpNode.par.left = tmpNode;
}
else
{
if (tmpNode.par != null)
tmpNode.par.right = tmpNode;
}
root = tmpNode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent
{
height = 1,
left = null,
right = null,
par = parent,
key = key
};
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.left != null && key < root.left.key)
{
root = LLR(root);
}
else
{
root = LRR(root);
}
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.right != null && key < root.right.key)
{
root = RLR(root);
}
else
{
root = RRR(root);
}
}
}
else
{
// Case when given key is already in the tree
}
UpdateHeight(root);
return root;
}
public static void PrintPreorder(AVLwithparent root)
{
Console.Write("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
Console.WriteLine(root.par.key);
else
Console.WriteLine("NULL");
if (root.left != null)
{
PrintPreorder(root.left);
}
if (root.right != null)
{
PrintPreorder(root.right);
}
}
public static void Main()
{
AVLwithparent root = null;
root = Insert(root, null, 10);
root = Insert(root, null, 20);
root = Insert(root, null, 30);
root = Insert(root, null, 40);
root = Insert(root, null, 50);
root = Insert(root, null, 25);
PrintPreorder(root);
}
}
JavaScript
class AVLwithparent {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
this.par = null;
this.height = 1;
}
}
// Function to update the height of a node based on its children's heights
function updateHeight(root) {
if (root !== null) {
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
root.height = Math.max(leftHeight, rightHeight) + 1;
}
}
// Left-Left Rotation (LLR) to balance the AVL tree
function LLR(root) {
const tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right !== null) {
tmpnode.right.par = root;
}
tmpnode.right = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par !== null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Right-Right Rotation (RRR) to balance the AVL tree
function RRR(root) {
const tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left !== null) {
tmpnode.left.par = root;
}
tmpnode.left = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par !== null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Left-Right Rotation (LRR) to balance the AVL tree
function LRR(root) {
root.left = RRR(root.left);
return LLR(root);
}
// Right-Left Rotation (RLR) to balance the AVL tree
function RLR(root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a key into the AVL tree and balance the tree if needed
function insert(root, parent, key) {
if (root === null) {
root = new AVLwithparent(key);
root.par = parent;
} else if (root.key > key) {
root.left = insert(root.left, root, key);
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) === 2) {
if (key < root.left.key) {
root = LLR(root);
} else {
root = LRR(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) === 2) {
if (key < root.right.key) {
root = RLR(root);
} else {
root = RRR(root);
}
}
}
updateHeight(root);
return root;
}
// Function to print the nodes of the AVL tree in preorder
function printPreorder(root) {
if (root !== null) {
const parentKey = (root.par !== null) ? root.par.key : "NULL";
console.log(`Node: ${root.key}, Parent Node: ${parentKey}`);
printPreorder(root.left);
printPreorder(root.right);
}
}
// Example usage
let root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
printPreorder(root);
OutputNode: 30, Parent Node: NULL
Node: 20, Parent Node: 30
Node: 10, Parent Node: 20
Node: 25, Parent Node: 20
Node: 40, Parent Node: 30
Node: 50, Parent Node: 40
Time Complexity: O(log N), where N is the number of nodes of the tree.
Auxiliary Space: O(1)
Search Operation: The search operation in an AVL tree with parent pointers is similar to the search operation in a normal Binary Search Tree. Follow the steps below to perform search operation:
- Start from the root node.
- If the root node is NULL, return false.
- Check if the current node’s value is equal to the value of the node to be searched. If yes, return true.
- If the current node’s value is less than searched key then recur to the right subtree.
- If the current node’s value is greater than searched key then recur to the left subtree.
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and the right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of the left
// child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the right
// child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
if (root == NULL) {
cout << "Error in memory" << endl;
}
// Otherwise
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Stores the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right, root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to find a key in AVL tree
bool AVLsearch(
struct AVLwithparent* root, int key)
{
// If root is NULL
if (root == NULL)
return false;
// If found, return true
else if (root->key == key)
return true;
// Recur to the left subtree if
// the current node's value is
// greater than key
else if (root->key > key) {
bool val = AVLsearch(root->left, key);
return val;
}
// Otherwise, recur to the
// right subtree
else {
bool val = AVLsearch(root->right, key);
return val;
}
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function call to insert the nodes
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 20);
root = Insert(root, NULL, 30);
root = Insert(root, NULL, 40);
root = Insert(root, NULL, 50);
root = Insert(root, NULL, 25);
// Function call to search for a node
bool found = AVLsearch(root, 40);
if (found)
cout << "value found";
else
cout << "value not found";
return 0;
}
Java
class AVLwithparent {
AVLwithparent left, right, par;
int key;
int height;
// Constructor
public AVLwithparent(int key, AVLwithparent parent) {
this.key = key;
this.par = parent;
this.height = 1;
}
}
public class AVLTree {
// Function to update the height of a node according to its children's node's heights
public static void updateHeight(AVLwithparent root) {
if (root != null) {
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.max(val, root.right.height + 1);
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent llr(AVLwithparent root) {
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent rrr(AVLwithparent root) {
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent lrr(AVLwithparent root) {
root.left = rrr(root.left);
return llr(root);
}
// Function to handle right left case
public static AVLwithparent rlr(AVLwithparent root) {
root.right = llr(root.right);
return rrr(root);
}
// Function to insert a node in the AVL tree
public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
root = new AVLwithparent(key, parent);
} else if (root.key > key) {
root.left = insert(root.left, root, key);
int firstHeight = (root.left != null) ? root.left.height : 0;
int secondHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) == 2) {
if (root.left != null && key < root.left.key)
root = llr(root);
else
root = lrr(root);
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
int firstHeight = (root.left != null) ? root.left.height : 0;
int secondHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) == 2) {
if (root.right != null && key < root.right.key)
root = rlr(root);
else
root = rrr(root);
}
}
updateHeight(root);
return root;
}
// Function to find a key in AVL tree
public static boolean avlSearch(AVLwithparent root, int key) {
if (root == null)
return false;
else if (root.key == key)
return true;
else if (root.key > key)
return avlSearch(root.left, key);
else
return avlSearch(root.right, key);
}
// Driver Code
public static void main(String[] args) {
AVLwithparent root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
boolean found = avlSearch(root, 40);
if (found)
System.out.println("Value found");
else
System.out.println("Value not found");
}
}
Python
# Python program for the above approach
# AVL tree node
class AVLwithparent:
def __init__(self, key, parent=None):
self.left = None
self.right = None
self.key = key
self.par = parent
self.height = 1
# Function to update the height of
# a node according to its children's
# node's heights
def update_height(root):
if root is not None:
# Store the height of the
# current node
val = 1
# Store the height of the left
# and the right subtree
if root.left is not None:
val = root.left.height + 1
if root.right is not None:
val = max(val, root.right.height + 1)
# Update the height of the
# current node
root.height = val
# Function to handle Left Left Case
def llr(root):
# Create a reference to the
# left child
tmp_node = root.left
# Update the left child of the
# root to the right child of the
# current left child of the root
root.left = tmp_node.right
# Update parent pointer of the left
# child of the root node
if tmp_node.right is not None:
tmp_node.right.par = root
# Update the right child of
# tmp_node to root
tmp_node.right = root
# Update parent pointer of tmp_node
tmp_node.par = root.par
# Update the parent pointer of root
root.par = tmp_node
# Update tmp_node as the left or
# the right child of its parent
# pointer according to its key value
if tmp_node.par is not None and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
else:
if tmp_node.par is not None:
tmp_node.par.right = tmp_node
# Make tmp_node as the new root
root = tmp_node
# Update the heights
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
# Return the root node
return root
# Function to handle Right Right Case
def rrr(root):
# Create a reference to the
# right child
tmp_node = root.right
# Update the right child of the
# root as the left child of the
# current right child of the root
root.right = tmp_node.left
# Update parent pointer of the right
# child of the root node
if tmp_node.left is not None:
tmp_node.left.par = root
# Update the left child of the
# tmp_node to root
tmp_node.left = root
# Update parent pointer of tmp_node
tmp_node.par = root.par
# Update the parent pointer of root
root.par = tmp_node
# Update tmp_node as the left or
# the right child of its parent
# pointer according to its key value
if tmp_node.par is not None and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
else:
if tmp_node.par is not None:
tmp_node.par.right = tmp_node
# Make tmp_node as the new root
root = tmp_node
# Update the heights
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
# Return the root node
return root
# Function to handle Left Right Case
def lrr(root):
root.left = rrr(root.left)
return llr(root)
# Function to handle Right Left Case
def rlr(root):
root.right = llr(root.right)
return rrr(root)
# Function to insert a node in
# the AVL tree
def insert(root, parent, key):
if root is None:
# Create and assign values
# to a new node
root = AVLwithparent(key, parent)
else:
if root.key > key:
# Recur to the left subtree
# to insert the node
root.left = insert(root.left, root, key)
# Stores the heights of the
# left and right subtree
first_height = 0
second_height = 0
if root.left is not None:
first_height = root.left.height
if root.right is not None:
second_height = root.right.height
# Balance the tree if the
# current node is not balanced
if abs(first_height - second_height) == 2:
if root.left is not None and key < root.left.key:
# Left Left Case
root = llr(root)
else:
# Left Right Case
root = lrr(root)
elif root.key < key:
# Recur to the right subtree
# to insert the node
root.right = insert(root.right, root, key)
# Store the heights of the left
# and right subtree
first_height = 0
second_height = 0
if root.left is not None:
first_height = root.left.height
if root.right is not None:
second_height = root.right.height
# Balance the tree if the
# current node is not balanced
if abs(first_height - second_height) == 2:
if root.right is not None and key < root.right.key:
# Right Left Case
root = rlr(root)
else:
# Right Right Case
root = rrr(root)
# Update the height of the
# root node
update_height(root)
# Return the root node
return root
# Function to find a key in AVL tree
def avl_search(root, key):
# If root is None
if root is None:
return False
# If found, return True
elif root.key == key:
return True
# Recur to the left subtree if
# the current node's value is
# greater than key
elif root.key > key:
return avl_search(root.left, key)
# Otherwise, recur to the
# right subtree
else:
return avl_search(root.right, key)
# Driver Code
if __name__ == "__main__":
root = None
# Function call to insert the nodes
root = insert(root, None, 10)
root = insert(root, None, 20)
root = insert(root, None, 30)
root = insert(root, None, 40)
root = insert(root, None, 50)
root = insert(root, None, 25)
# Function call to search for a node
found = avl_search(root, 40)
if found:
print("Value found")
else:
print("Value not found")
C#
using System;
// AVL tree node
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public int key;
public AVLwithparent par;
public int height;
}
public class AVLTree
{
// Function to update the height of a node according to its children's node's heights
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a node in the AVL tree
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent();
root.height = 1;
root.left = null;
root.right = null;
root.par = parent;
root.key = key;
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.left != null && key < root.left.key)
root = LLR(root);
else
root = LRR(root);
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.right != null && key < root.right.key)
root = RLR(root);
else
root = RRR(root);
}
}
UpdateHeight(root);
return root;
}
// Function to find a key in AVL tree
public static bool AVLSearch(AVLwithparent root, int key)
{
if (root == null)
return false;
else if (root.key == key)
return true;
else if (root.key > key)
return AVLSearch(root.left, key);
else
return AVLSearch(root.right, key);
}
// Driver Code
public static void Main(string[] args)
{
AVLwithparent root = null;
root = Insert(root, null, 10);
root = Insert(root, null, 20);
root = Insert(root, null, 30);
root = Insert(root, null, 40);
root = Insert(root, null, 50);
root = Insert(root, null, 25);
bool found = AVLSearch(root, 40);
if (found)
Console.WriteLine("Value found");
else
Console.WriteLine("Value not found");
}
}
JavaScript
class AVLwithparent {
constructor(key, parent = null) {
this.left = null;
this.right = null;
this.key = key;
this.par = parent; // 'par' keeps track of the parent node
this.height = 1; // Height of the node initialized to 1
}
}
// Function to update the height of a node
function updateHeight(root) {
if (root !== null) {
let val = 1;
if (root.left !== null) {
val = root.left.height + 1; // Update height considering the left subtree
}
if (root.right !== null) {
val = Math.max(val, root.right.height + 1); // Update height considering the right subtree
}
root.height = val; // Update the height of the current node
}
}
// Left-Left Rotation (LLR)
function llr(root) {
let tmpNode = root.left;
root.left = tmpNode.right;
if (tmpNode.right !== null) {
tmpNode.right.par = root;
}
tmpNode.right = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par !== null && root.key < tmpNode.par.key) {
tmpNode.par.left = tmpNode;
} else {
if (tmpNode.par !== null) {
tmpNode.par.right = tmpNode;
}
}
root = tmpNode;
// Update heights after rotation
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Right-Right Rotation (RRR)
function rrr(root) {
let tmpNode = root.right;
root.right = tmpNode.left;
if (tmpNode.left !== null) {
tmpNode.left.par = root;
}
tmpNode.left = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par !== null && root.key < tmpNode.par.key) {
tmpNode.par.left = tmpNode;
} else {
if (tmpNode.par !== null) {
tmpNode.par.right = tmpNode;
}
}
root = tmpNode;
// Update heights after rotation
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Left-Right Rotation (LRR)
function lrr(root) {
root.left = rrr(root.left);
return llr(root);
}
// Right-Left Rotation (RLR)
function rlr(root) {
root.right = llr(root.right);
return rrr(root);
}
// Function to insert a node into the AVL tree
function insert(root, parent, key) {
if (root === null) {
root = new AVLwithparent(key, parent);
} else {
if (root.key > key) {
root.left = insert(root.left, root, key);
// Perform rotations if necessary after insertion
let firstHeight = root.left ? root.left.height : 0;
let secondHeight = root.right ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) === 2) {
if (root.left !== null && key < root.left.key) {
root = llr(root);
} else {
root = lrr(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
// Perform rotations if necessary after insertion
let firstHeight = root.left ? root.left.height : 0;
let secondHeight = root.right ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) === 2) {
if (root.right !== null && key < root.right.key) {
root = rlr(root);
} else {
root = rrr(root);
}
}
}
}
updateHeight(root); // Update the height of the current node
return root;
}
// Function to search for a node in the AVL tree
function avlSearch(root, key) {
if (root === null) {
return false;
} else if (root.key === key) {
return true;
} else if (root.key > key) {
return avlSearch(root.left, key);
} else {
return avlSearch(root.right, key);
}
}
// Driver Code
let root = null;
// Inserting nodes into the AVL tree
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
// Searching for a value in the AVL tree
let found = avlSearch(root, 40);
if (found) {
console.log("Value found");
} else {
console.log("Value not found");
}
Time Complexity: O(log N), where N is the number of nodes of the tree
Auxiliary Space: O(1)
Delete Operation: The deletion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the references to the parent pointers need to be updated with every deletion and rotation accordingly. Follow the steps below to perform the delete operation:
- Perform the delete procedure as in a normal BST.
- From the node that has been deleted, move towards the root.
- At each node on the path, update the height of the node.
- Check for AVL conditions at each node. Let there be 3 nodes: w, x, y where w is the current node, x is the root of the subtree of w which has greater height and y is the root of the subtree of x which has greater height.
- If the node w is unbalanced, there exists one of the following 4 cases:
- Left Left Case (x is left child of w and y is left child of x)
- Left Right Case (x is left child of w and y is right child of x)
- Right Left Case (x is right child of w and y is left child of x)
- Right Right Case (x is right child of w and y is right child of x)
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(struct AVLwithparent* root)
{
// Print the node's value along
// with its parent value
cout << "Node: " << root->key
<< ", Parent Node: ";
if (root->par != NULL)
cout << root->par->key << endl;
else
cout << "NULL" << endl;
// Recur to the left subtree
if (root->left != NULL) {
printpreorder(root->left);
}
// Recur to the right subtree
if (root->right != NULL) {
printpreorder(root->right);
}
}
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of left
// child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the
// right child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to balance the tree after
// deletion of a node
struct AVLwithparent* Balance(
struct AVLwithparent* root)
{
// Store the current height of
// the left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// If current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (firstheight < secondheight) {
// Store the height of the
// left and right subtree
// of the current node's
// right subtree
int rightheight1 = 0;
int rightheight2 = 0;
if (root->right->right != NULL)
rightheight2 = root->right->right->height;
if (root->right->left != NULL)
rightheight1 = root->right->left->height;
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
else {
// Store the height of the
// left and right subtree
// of the current node's
// left subtree
int leftheight1 = 0;
int leftheight2 = 0;
if (root->left->right != NULL)
leftheight2 = root->left->right->height;
if (root->left->left != NULL)
leftheight1 = root->left->left->height;
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
if (root == NULL)
cout << "Error in memory" << endl;
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right,
root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to delete a node from
// the AVL tree
struct AVLwithparent* Delete(
struct AVLwithparent* root,
int key)
{
if (root != NULL) {
// If the node is found
if (root->key == key) {
// Replace root with its
// left child
if (root->right == NULL
&& root->left != NULL) {
if (root->par != NULL) {
if (root->par->key
< root->key)
root->par->right = root->left;
else
root->par->left = root->left;
// Update the height
// of root's parent
Updateheight(root->par);
}
root->left->par = root->par;
// Balance the node
// after deletion
root->left = Balance(
root->left);
return root->left;
}
// Replace root with its
// right child
else if (root->left == NULL
&& root->right != NULL) {
if (root->par != NULL) {
if (root->par->key
< root->key)
root->par->right = root->right;
else
root->par->left = root->right;
// Update the height
// of the root's parent
Updateheight(root->par);
}
root->right->par = root->par;
// Balance the node after
// deletion
root->right = Balance(root->right);
return root->right;
}
// Remove the references of
// the current node
else if (root->left == NULL
&& root->right == NULL) {
if (root->par->key < root->key) {
root->par->right = NULL;
}
else {
root->par->left = NULL;
}
if (root->par != NULL)
Updateheight(root->par);
root = NULL;
return NULL;
}
// Otherwise, replace the
// current node with its
// successor and then
// recursively call Delete()
else {
struct AVLwithparent* tmpnode = root;
tmpnode = tmpnode->right;
while (tmpnode->left != NULL) {
tmpnode = tmpnode->left;
}
int val = tmpnode->key;
root->right
= Delete(root->right, tmpnode->key);
root->key = val;
// Balance the node
// after deletion
root = Balance(root);
}
}
// Recur to the right subtree to
// delete the current node
else if (root->key < key) {
root->right = Delete(root->right, key);
root = Balance(root);
}
// Recur into the right subtree
// to delete the current node
else if (root->key > key) {
root->left = Delete(root->left, key);
root = Balance(root);
}
// Update height of the root
if (root != NULL) {
Updateheight(root);
}
}
// Handle the case when the key to be
// deleted could not be found
else {
cout << "Key to be deleted "
<< "could not be found\n";
}
// Return the root node
return root;
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function call to insert the nodes
root = Insert(root, NULL, 9);
root = Insert(root, NULL, 5);
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 0);
root = Insert(root, NULL, 6);
// Print the tree before deleting node
cout << "Before deletion:\n";
printpreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
cout << "After deletion:\n";
printpreorder(root);
}
Java
// Java program for the above approach
class AVLwithparent {
AVLwithparent left, right, par;
int key, height;
AVLwithparent(int item) {
key = item;
height = 1;
}
}
public class AVLTreeWithParent {
// Function to print the preorder
// traversal of the AVL tree
static void printPreorder(AVLwithparent root) {
if (root != null) {
// Print the node's value along
// with its parent value
System.out.print("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
System.out.println(root.par.key);
else
System.out.println("NULL");
// Recur to the left subtree
printPreorder(root.left);
// Recur to the right subtree
printPreorder(root.right);
}
}
// Function to update the height of
// a node according to its children's
// node's heights
static void updateHeight(AVLwithparent root) {
if (root != null) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.max(val, root.right.height + 1);
// Update the height of the
// current node
root.height = val;
}
}
// Function to handle Left Left Case
static AVLwithparent LLR(AVLwithparent root) {
// Create a reference to the
// left child
AVLwithparent tmpnode = root.left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root.left = tmpnode.right;
// Update parent pointer of left
// child of the root node
if (tmpnode.right != null)
tmpnode.right.par = root;
// Update the right child of
// tmpnode to root
tmpnode.right = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
// Return the root node
return root;
}
// Function to handle Right Right Case
static AVLwithparent RRR(AVLwithparent root) {
// Create a reference to the
// right child
AVLwithparent tmpnode = root.right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root.right = tmpnode.left;
// Update parent pointer of the
// right child of the root node
if (tmpnode.left != null)
tmpnode.left.par = root;
// Update the left child of the
// tmpnode to root
tmpnode.left = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
// Return the root node
return root;
}
// Function to handle Left Right Case
static AVLwithparent LRR(AVLwithparent root) {
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
static AVLwithparent RLR(AVLwithparent root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to balance the tree after
// deletion of a node
static AVLwithparent balance(AVLwithparent root) {
// Store the current height of
// the left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// If current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (firstheight < secondheight) {
// Store the height of the
// left and right subtree
// of the current node's
// right subtree
int rightheight1 = 0;
int rightheight2 = 0;
if (root.right.right != null)
rightheight2 = root.right.right.height;
if (root.right.left != null)
rightheight1 = root.right.left.height;
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
} else {
// Store the height of the
// left and right subtree
// of the current node's
// left subtree
int leftheight1 = 0;
int leftheight2 = 0;
if (root.left.right != null)
leftheight2 = root.left.right.height;
if (root.left.left != null)
leftheight1 = root.left.left.height;
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to insert a node in
// the AVL tree
static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
// Create and assign values
// to a new node
root = new AVLwithparent(key);
if (root == null)
System.out.println("Error in memory");
else {
root.height = 1;
root.left = null;
root.right = null;
root.par = parent;
}
} else if (root.key > key) {
// Recur to the left subtree
// to insert the node
root.left = insert(root.left, root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// Balance the tree if the
// current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (root.left != null && key < root.left.key) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
} else if (root.key < key) {
// Recur to the right subtree
// to insert the node
root.right = insert(root.right, root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// Balance the tree if the
// current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (root.right != null && key < root.right.key) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
// Do nothing
// Update the height of the
// root node
updateHeight(root);
// Return the root node
return root;
}
// Function to delete a node from
// the AVL tree
static AVLwithparent delete(AVLwithparent root, int key) {
if (root != null) {
// If the node is found
if (root.key == key) {
// Replace root with its
// left child
if (root.right == null && root.left != null) {
if (root.par != null) {
if (root.par.key < root.key)
root.par.right = root.left;
else
root.par.left = root.left;
// Update the height
// of root's parent
updateHeight(root.par);
}
root.left.par = root.par;
// Balance the node
// after deletion
root.left = balance(root.left);
return root.left;
}
// Replace root with its
// right child
else if (root.left == null && root.right != null) {
if (root.par != null) {
if (root.par.key < root.key)
root.par.right = root.right;
else
root.par.left = root.right;
// Update the height
// of the root's parent
updateHeight(root.par);
}
root.right.par = root.par;
// Balance the node after
// deletion
root.right = balance(root.right);
return root.right;
}
// Remove the references of
// the current node
else if (root.left == null && root.right == null) {
if (root.par.key < root.key) {
root.par.right = null;
} else {
root.par.left = null;
}
if (root.par != null)
updateHeight(root.par);
root = null;
return null;
}
// Otherwise, replace the
// current node with its
// successor and then
// recursively call delete()
else {
AVLwithparent tmpnode = root;
tmpnode = tmpnode.right;
while (tmpnode.left != null) {
tmpnode = tmpnode.left;
}
int val = tmpnode.key;
root.right = delete(root.right, tmpnode.key);
root.key = val;
// Balance the node
// after deletion
root = balance(root);
}
}
// Recur to the right subtree to
// delete the current node
else if (root.key < key) {
root.right = delete(root.right, key);
root = balance(root);
}
// Recur into the right subtree
// to delete the current node
else if (root.key > key) {
root.left = delete(root.left, key);
root = balance(root);
}
// Update height of the root
if (root != null) {
updateHeight(root);
}
}
// Handle the case when the key to be
// deleted could not be found
else {
System.out.println("Key to be deleted could not be found");
}
// Return the root node
return root;
}
// Driver Code
public static void main(String[] args) {
AVLwithparent root = null;
// Function call to insert the nodes
root = insert(root, null, 9);
root = insert(root, null, 5);
root = insert(root, null, 10);
root = insert(root, null, 0);
root = insert(root, null, 6);
// Print the tree before deleting node
System.out.println("Before deletion:");
printPreorder(root);
// Function Call to delete node 10
root = delete(root, 10);
// Print the tree after deleting node
System.out.println("After deletion:");
printPreorder(root);
}
}
Python
class AVLwithparent:
def __init__(self, key, parent=None):
self.left = None
self.right = None
self.key = key
self.par = parent
self.height = 1
def print_preorder(root):
if root:
print("Node:", root.key, ", Parent Node:", root.par.key if root.par else "NULL")
print_preorder(root.left)
print_preorder(root.right)
def update_height(root):
if root:
val = 1
if root.left:
val = root.left.height + 1
if root.right:
val = max(val, root.right.height + 1)
root.height = val
def llr(root):
tmp_node = root.left
root.left = tmp_node.right
if tmp_node.right:
tmp_node.right.par = root
tmp_node.right = root
tmp_node.par = root.par
root.par = tmp_node
if tmp_node.par and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
elif tmp_node.par:
tmp_node.par.right = tmp_node
root = tmp_node
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
return root
def rrr(root):
tmp_node = root.right
root.right = tmp_node.left
if tmp_node.left:
tmp_node.left.par = root
tmp_node.left = root
tmp_node.par = root.par
root.par = tmp_node
if tmp_node.par and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
elif tmp_node.par:
tmp_node.par.right = tmp_node
root = tmp_node
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
return root
def lrr(root):
root.left = rrr(root.left)
return llr(root)
def rlr(root):
root.right = llr(root.right)
return rrr(root)
def balance(root):
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if first_height < second_height:
rightheight1 = 0
rightheight2 = 0
if root.right.right:
rightheight2 = root.right.right.height
if root.right.left:
rightheight1 = root.right.left.height
if rightheight1 > rightheight2:
root = rlr(root)
else:
root = rrr(root)
else:
leftheight1 = 0
leftheight2 = 0
if root.left.right:
leftheight2 = root.left.right.height
if root.left.left:
leftheight1 = root.left.left.height
if leftheight1 > leftheight2:
root = llr(root)
else:
root = lrr(root)
return root
def insert(root, parent, key):
if root is None:
root = AVLwithparent(key, parent)
elif root.key > key:
root.left = insert(root.left, root, key)
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if root.left and key < root.left.key:
root = llr(root)
else:
root = lrr(root)
elif root.key < key:
root.right = insert(root.right, root, key)
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if root.right and key < root.right.key:
root = rlr(root)
else:
root = rrr(root)
update_height(root)
return root
def delete(root, key):
if root:
if root.key == key:
if root.right is None and root.left is not None:
if root.par:
if root.par.key < root.key:
root.par.right = root.left
else:
root.par.left = root.left
update_height(root.par)
root.left.par = root.par
root.left = balance(root.left)
return root.left
elif root.left is None and root.right is not None:
if root.par:
if root.par.key < root.key:
root.par.right = root.right
else:
root.par.left = root.right
update_height(root.par)
root.right.par = root.par
root.right = balance(root.right)
return root.right
elif root.left is None and root.right is None:
if root.par:
if root.par.key < root.key:
root.par.right = None
else:
root.par.left = None
update_height(root.par)
root = None
return None
else:
tmp_node = root
tmp_node = tmp_node.right
while tmp_node.left:
tmp_node = tmp_node.left
val = tmp_node.key
root.right = delete(root.right, tmp_node.key)
root.key = val
root = balance(root)
elif root.key < key:
root.right = delete(root.right, key)
root = balance(root)
elif root.key > key:
root.left = delete(root.left, key)
root = balance(root)
update_height(root)
return root
# Driver Code
if __name__ == "__main__":
root = None
# Function call to insert the nodes
root = insert(root, None, 9)
root = insert(root, None, 5)
root = insert(root, None, 10)
root = insert(root, None, 0)
root = insert(root, None, 6)
# Print the tree before deleting node
print("Before deletion:")
print_preorder(root)
# Function Call to delete node 10
root = delete(root, 10)
# Print the tree after deleting node
print("After deletion:")
print_preorder(root)
C#
using System;
// AVL tree node
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public AVLwithparent par;
public int key;
public int height;
public AVLwithparent(int key)
{
this.key = key;
this.height = 1;
}
}
public class AVLTreeWithParent
{
// Function to print the preorder traversal of the AVL tree
public static void PrintPreorder(AVLwithparent root)
{
if (root != null)
{
// Print the node's value along with its parent value
Console.Write("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
Console.WriteLine(root.par.key);
else
Console.WriteLine("NULL");
// Recur to the left subtree
PrintPreorder(root.left);
// Recur to the right subtree
PrintPreorder(root.right);
}
}
// Function to update the height of a node according to its children's node's heights
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
// Store the height of the current node
int val = 1;
// Store the height of the left and right subtree
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
// Update the height of the current node
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root.par = tmpnode;
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root.par = tmpnode;
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
// Function to balance the tree after deletion of a node
public static AVLwithparent Balance(AVLwithparent root)
{
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
if (Math.Abs(firstheight - secondheight) == 2)
{
if (firstheight < secondheight)
{
int rightheight1 = 0;
int rightheight2 = 0;
if (root.right.right != null)
rightheight2 = root.right.right.height;
if (root.right.left != null)
rightheight1 = root.right.left.height;
if (rightheight1 > rightheight2)
root = RLR(root);
else
root = RRR(root);
}
else
{
int leftheight1 = 0;
int leftheight2 = 0;
if (root.left.right != null)
leftheight2 = root.left.right.height;
if (root.left.left != null)
leftheight1 = root.left.left.height;
if (leftheight1 > leftheight2)
root = LLR(root);
else
root = LRR(root);
}
}
return root;
}
// Function to insert a node in the AVL tree
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent(key);
root.par = parent;
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)
{
if (root.left != null && key < root.left.key)
root = LLR(root);
else
root = LRR(root);
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)
{
if (root.right != null && key < root.right.key)
root = RLR(root);
else
root = RRR(root);
}
}
UpdateHeight(root);
return root;
}
// Function to delete a node from the AVL tree
public static AVLwithparent Delete(AVLwithparent root, int key)
{
if (root != null)
{
if (root.key == key)
{
if (root.right == null && root.left != null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = root.left;
else
root.par.left = root.left;
UpdateHeight(root.par);
}
root.left.par = root.par;
root.left = Balance(root.left);
return root.left;
}
else if (root.left == null && root.right != null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = root.right;
else
root.par.left = root.right;
UpdateHeight(root.par);
}
root.right.par = root.par;
root.right = Balance(root.right);
return root.right;
}
else if (root.left == null && root.right == null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = null;
else
root.par.left = null;
UpdateHeight(root.par);
}
root = null;
return null;
}
else
{
AVLwithparent tmpnode = root.right;
while (tmpnode.left != null)
tmpnode = tmpnode.left;
int val = tmpnode.key;
root.right = Delete(root.right, tmpnode.key);
root.key = val;
root = Balance(root);
}
}
else if (root.key < key)
{
root.right = Delete(root.right, key);
root = Balance(root);
}
else if (root.key > key)
{
root.left = Delete(root.left, key);
root = Balance(root);
}
UpdateHeight(root);
}
else
Console.WriteLine("Key to be deleted could not be found");
return root;
}
// Driver Code
public static void Main(string[] args)
{
AVLwithparent root = null;
// Function call to insert the nodes
root = Insert(root, null, 9);
root = Insert(root, null, 5);
root = Insert(root, null, 10);
root = Insert(root, null, 0);
root = Insert(root, null, 6);
// Print the tree before deleting node
Console.WriteLine("Before deletion:");
PrintPreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
Console.WriteLine("After deletion:");
PrintPreorder(root);
}
}
//This code is contributed by Utkarsh
JavaScript
// AVL tree node
class AVLwithparent {
constructor(key) {
this.left = null;
this.right = null;
this.key = key;
this.par = null;
this.height = 1;
}
}
// Function to print the preorder traversal of the AVL tree
function printpreorder(root) {
if (root !== null) {
// Print the node's value along with its parent value
console.log(`Node: ${root.key}, Parent Node: ${root.par ? root.par.key : 'NULL'}`);
// Recur to the left subtree
printpreorder(root.left);
// Recur to the right subtree
printpreorder(root.right);
}
}
// Function to update the height of a node according to its children's node's heights
function Updateheight(root) {
if (root !== null) {
// Store the height of the current node
let val = 1;
// Store the height of the left and right subtree
if (root.left !== null) {
val = root.left.height + 1;
}
if (root.right !== null) {
val = Math.max(val, root.right.height + 1);
}
// Update the height of the current node
root.height = val;
}
}
// Function to handle Left Left Case
function LLR(root) {
// Create a reference to the left child
const tmpnode = root.left;
// Update the left child of the root to the right child of the current left child of the root
root.left = tmpnode.right;
// Update parent pointer of left child of the root node
if (tmpnode.right !== null) {
tmpnode.right.par = root;
}
// Update the right child of tmpnode to root
tmpnode.right = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
root.par = tmpnode;
// Update tmpnode as the left or the right child of its parent pointer according to its key value
if (tmpnode.par !== null && root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
if (tmpnode.par !== null) {
tmpnode.par.right = tmpnode;
}
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root.left);
Updateheight(root.right);
Updateheight(root);
Updateheight(root.par);
// Return the root node
return root;
}
// Function to handle Right Right Case
function RRR(root) {
// Create a reference to the right child
const tmpnode = root.right;
// Update the right child of the root as the left child of the current right child of the root
root.right = tmpnode.left;
// Update parent pointer of the right child of the root node
if (tmpnode.left !== null) {
tmpnode.left.par = root;
}
// Update the left child of the tmpnode to root
tmpnode.left = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
root.par = tmpnode;
// Update tmpnode as the left or the right child of its parent pointer according to its key value
if (tmpnode.par !== null && root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
if (tmpnode.par !== null) {
tmpnode.par.right = tmpnode;
}
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root.left);
Updateheight(root.right);
Updateheight(root);
Updateheight(root.par);
// Return the root node
return root;
}
// Function to handle Left Right Case
function LRR(root) {
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle Right Left Case
function RLR(root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to Balance the tree after deletion of a node
function Balance(root) {
// Store the current height of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// If the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (firstheight < secondheight) {
// Store the height of the left and right subtree of the current node's right subtree
let rightheight1 = 0;
let rightheight2 = 0;
if (root.right.right !== null) {
rightheight2 = root.right.right.height;
}
if (root.right.left !== null) {
rightheight1 = root.right.left.height;
}
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
} else {
// Store the height of the left and right subtree of the current node's left subtree
let leftheight1 = 0;
let leftheight2 = 0;
if (root.left.right !== null) {
leftheight2 = root.left.right.height;
}
if (root.left.left !== null) {
leftheight1 = root.left.left.height;
}
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to Insert a node in the AVL tree
function Insert(root, parent, key) {
if (root === null) {
// Create and assign values to a new node
root = new AVLwithparent(key);
if (root === null) {
console.log("Error in memory");
} else {
root.par = parent;
}
} else if (root.key > key) {
// Recur to the left subtree to Insert the node
root.left = Insert(root.left, root, key);
// Store the heights of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// Balance the tree if the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (root.left !== null && key < root.left.key) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
} else if (root.key < key) {
// Recur to the right subtree to Insert the node
root.right = Insert(root.right, root, key);
// Store the heights of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// Balance the tree if the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (root.right !== null && key < root.right.key) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is already in tree
else {
// Do nothing
}
// Update the height of the root node
Updateheight(root);
// Return the root node
return root;
}
// Function to delete a node from the AVL tree
function Delete(root, key) {
if (root !== null) {
// If the node is found
if (root.key === key) {
// Replace root with its left child
if (root.right === null && root.left !== null) {
if (root.par !== null) {
if (root.par.key < root.key) {
root.par.right = root.left;
} else {
root.par.left = root.left;
}
// Update the height of root's parent
Updateheight(root.par);
}
root.left.par = root.par;
// Balance the node after deletion
root.left = Balance(root.left);
return root.left;
}
// Replace root with its right child
else if (root.left === null && root.right !== null) {
if (root.par !== null) {
if (root.par.key < root.key) {
root.par.right = root.right;
} else {
root.par.left = root.right;
}
// Update the height of the root's parent
Updateheight(root.par);
}
root.right.par = root.par;
// Balance the node after deletion
root.right = Balance(root.right);
return root.right;
}
// Delete the references of the current node
else if (root.left === null && root.right === null) {
if (root.par.key < root.key) {
root.par.right = null;
} else {
root.par.left = null;
}
if (root.par !== null) {
Updateheight(root.par);
}
root = null;
return null;
}
// Otherwise, replace the current node with its successor and then recursively call Delete()
else {
let tmpnode = root;
tmpnode = tmpnode.right;
while (tmpnode.left !== null) {
tmpnode = tmpnode.left;
}
let val = tmpnode.key;
root.right = Delete(root.right, tmpnode.key);
root.key = val;
// Balance the node after deletion
root = Balance(root);
}
}
// Recur to the right subtree to delete the current node
else if (root.key < key) {
root.right = Delete(root.right, key);
root = Balance(root);
}
// Recur into the right subtree to delete the current node
else if (root.key > key) {
root.left = Delete(root.left, key);
root = Balance(root);
}
// Update height of the root
if (root !== null) {
Updateheight(root);
}
}
// Handle the case when the key to be deleted could not be found
else {
console.log("Key to be deleted could not be found");
}
// Return the root node
return root;
}
// Driver Code
let root = null;
// Function call to Insert the nodes
root = Insert(root, null, 9);
root = Insert(root, null, 5);
root = Insert(root, null, 10);
root = Insert(root, null, 0);
root = Insert(root, null, 6);
// Print the tree before deleting node
console.log("Before deletion:");
printpreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
console.log("After deletion:");
printpreorder(root);
// This Code is contributed by Yash Agarwal(yashagarwal2852002)
OutputBefore deletion:
Node: 9, Parent Node: NULL
Node: 5, Parent Node: 9
Node: 0, Parent Node: 5
Node: 6, Parent Node: 5
Node: 10, Parent Node: 9
After deletion:
Node: 6, Parent Node: NULL
Node: 5, Parent ...
Time Complexity: O(log N), where N is the number of nodes of the tree
Auxiliary Space: O(1)
Similar Reads
AVL Tree Data Structure
An AVL tree defined as a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees for any node cannot be more than one. The absolute difference between the heights of the left subtree and the right subtree for any node is known as the balance factor of
4 min read
What is AVL Tree | AVL Tree meaning
An AVL is a self-balancing Binary Search Tree (BST) where the difference between the heights of left and right subtrees of any node cannot be more than one. KEY POINTSIt is height balanced treeIt is a binary search treeIt is a binary tree in which the height difference between the left subtree and r
2 min read
Insertion in an AVL Tree
AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. Example of AVL Tree: The above tree is AVL because the differences between the heights of left and right subtrees for every node are less than
15+ min read
Insertion, Searching and Deletion in AVL trees containing a parent node pointer
AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. The insertion and deletion in AVL trees have been discussed in the previous article. In this article, insert, search, and delete operations are
15+ min read
Deletion in an AVL Tree
We have discussed AVL insertion in the previous post. 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. Followi
15+ min read
How is an AVL tree different from a B-tree?
AVL Trees: AVL tree is a self-balancing binary search tree in which each node maintain an extra factor which is called balance factor whose value is either -1, 0 or 1. B-Tree: A B-tree is a self - balancing tree data structure that keeps data sorted and allows searches, insertions, and deletions in
1 min read
Practice questions on Height balanced/AVL Tree
AVL tree is binary search tree with additional property that difference between height of left sub-tree and right sub-tree of any node canât be more than 1. Here are some key points about AVL trees: If there are n nodes in AVL tree, minimum height of AVL tree is floor(log 2 n). If there are n nodes
4 min read
AVL with duplicate keys
Please refer below post before reading about AVL tree handling of duplicates. How to handle duplicates in Binary Search Tree?This is to augment AVL tree node to store count together with regular fields like key, left and right pointers. Insertion of keys 12, 10, 20, 9, 11, 10, 12, 12 in an empty Bin
15+ min read
Count greater nodes in AVL tree
In this article we will see that how to calculate number of elements which are greater than given value in AVL tree. Examples: Input : x = 5 Root of below AVL tree 9 / \ 1 10 / \ \ 0 5 11 / / \ -1 2 6 Output : 4 Explanation: there are 4 values which are greater than 5 in AVL tree which are 6, 9, 10
15+ min read
Difference between Binary Search Tree and AVL Tree
Binary Search Tree:A binary Search Tree is a node-based binary tree data structure that has the following properties: The left subtree of a node contains only nodes with keys lesser than the nodeâs key.The right subtree of a node contains only nodes with keys greater than the nodeâs key.The left and
2 min read