Insertion, Searching and Deletion in AVL trees containing a parent node pointer (original) (raw)

Last Updated : 23 Jul, 2025

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:

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: <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>r</mi><mi>o</mi><mi>o</mi><mi>t</mi><mi mathvariant="normal">.</mi><mi>k</mi><mi>e</mi><mi>y</mi></mrow><mo separator="true">,</mo><mi>P</mi><mi>a</mi><mi>r</mi><mi>e</mi><mi>n</mi><mi>t</mi><mi>N</mi><mi>o</mi><mi>d</mi><mi>e</mi><mo>:</mo></mrow><annotation encoding="application/x-tex">{root.key}, Parent Node: </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">roo</span><span class="mord mathnormal">t</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">ey</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">a</span><span class="mord mathnormal">re</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10903em;">tN</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span>{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);

``

Output

Node: 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:

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:

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: <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>r</mi><mi>o</mi><mi>o</mi><mi>t</mi><mi mathvariant="normal">.</mi><mi>k</mi><mi>e</mi><mi>y</mi></mrow><mo separator="true">,</mo><mi>P</mi><mi>a</mi><mi>r</mi><mi>e</mi><mi>n</mi><mi>t</mi><mi>N</mi><mi>o</mi><mi>d</mi><mi>e</mi><mo>:</mo></mrow><annotation encoding="application/x-tex">{root.key}, Parent Node: </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">roo</span><span class="mord mathnormal">t</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">ey</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">a</span><span class="mord mathnormal">re</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10903em;">tN</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span>{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)

``

Output

Before 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)