Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on Tree
  • Practice Tree
  • MCQs on Tree
  • Tutorial on Tree
  • Types of Trees
  • Basic operations
  • Tree Traversal
  • Binary Tree
  • Complete Binary Tree
  • Ternary Tree
  • Binary Search Tree
  • Red-Black Tree
  • AVL Tree
  • Full Binary Tree
  • B-Tree
  • Advantages & Disadvantages
Open In App
Next Article:
Deletion in an AVL Tree
Next article icon

Insertion, Searching and Deletion in AVL trees containing a parent node pointer

Last Updated : 21 May, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. The insertion and deletion in AVL trees have been discussed in the previous article. In this article, insert, search, and delete operations are discussed on AVL trees that also have a parent pointer in their structure.

Definition of AVL tree node:

C++
struct AVLwithparent {      // Pointer to the left and the     // right subtree     struct AVLwithparent* left;     struct AVLwithparent* right;      // Stores the data in the node     int key;      // Stores the parent pointer     struct AVLwithparent* par;      // Stores the height of the     // current tree     int height; } 
Java
class AVLwithParent {     // Pointer to the left and the right subtree     AVLwithParent left;     AVLwithParent right;      // Stores the data in the node     int key;      // Stores the parent pointer     AVLwithParent par;      // Stores the height of the current tree     int height; } 
Python
# Python code  class AVLwithParent:     def __init__(self):         # Pointer to the left and the right subtree         self.left = None         self.right = None          # Stores the data in the node         self.key = None          # Stores the parent pointer         self.par = None          # Stores the height of the current tree         self.height = None  # This code is contributed by princekumaras 
C#
class AVLwithParent {     // Pointer to the left and the right subtree     public AVLwithParent left;     public AVLwithParent right;      // Stores the data in the node     public int key;      // Stores the parent pointer     public AVLwithParent par;      // Stores the height of the current tree     public int height; } 
JavaScript
class AVLwithParent {     constructor() {         // Pointer to the left and the right subtree         this.left = null;         this.right = null;          // Stores the data in the node         this.key = null;          // Stores the parent pointer         this.par = null;          // Stores the height of the current tree         this.height = null;     } } 

Representation of the Node:

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

Insert Operation: The insertion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the parent pointers need to be updated with every insertion and rotation accordingly. Follow the steps below to perform insert operation:

  • Perform standard BST insert for the node to be placed at its correct position.
  • Increase the height of each node encountered by 1 while finding the correct position for the node to be inserted.
  • Update the parent and child pointers of the inserted node and its parent respectively.
  • Starting from the inserted node till the root node check if the AVL condition is satisfied for each node on this path.
  • If w is the node where the AVL condition is not satisfied then we have 4 cases:
    • Left Left Case: (If the left subtree of the left child of w has the inserted node)
    • Left Right Case: (If the right subtree of the left child of w has the inserted node)
    • Right Left Case: (If the left subtree of the right child of w has the inserted node)
    • Right Right Case: (If the right subtree of the right child of w has the inserted node)

Below is the implementation of the above approach:

C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;  // AVL tree node struct AVLwithparent {     struct AVLwithparent* left;     struct AVLwithparent* right;     int key;     struct AVLwithparent* par;     int height; };  // Function to update the height of // a node according to its children's // node's heights void Updateheight(     struct AVLwithparent* root) {     if (root != NULL) {          // Store the height of the         // current node         int val = 1;          // Store the height of the left         // and right subtree         if (root->left != NULL)             val = root->left->height + 1;          if (root->right != NULL)             val = max(                 val, root->right->height + 1);          // Update the height of the         // current node         root->height = val;     } }  // Function to handle Left Left Case struct AVLwithparent* LLR(     struct AVLwithparent* root) {     // Create a reference to the     // left child     struct AVLwithparent* tmpnode = root->left;      // Update the left child of the     // root to the right child of the     // current left child of the root     root->left = tmpnode->right;      // Update parent pointer of the     // left child of the root node     if (tmpnode->right != NULL)         tmpnode->right->par = root;      // Update the right child of     // tmpnode to root     tmpnode->right = root;      // Update parent pointer of     // the tmpnode     tmpnode->par = root->par;      // Update the parent pointer     // of the root     root->par = tmpnode;      // Update tmpnode as the left or the     // right child of its parent pointer     // according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Right Right Case struct AVLwithparent* RRR(     struct AVLwithparent* root) {     // Create a reference to the     // right child     struct AVLwithparent* tmpnode = root->right;      // Update the right child of the     // root as the left child of the     // current right child of the root     root->right = tmpnode->left;      // Update parent pointer of the     // right child of the root node     if (tmpnode->left != NULL)         tmpnode->left->par = root;      // Update the left child of the     // tmpnode to root     tmpnode->left = root;      // Update parent pointer of     // the tmpnode     tmpnode->par = root->par;      // Update the parent pointer     // of the root     root->par = tmpnode;      // Update tmpnode as the left or     // the right child of its parent     // pointer according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Left Right Case struct AVLwithparent* LRR(     struct AVLwithparent* root) {     root->left = RRR(root->left);     return LLR(root); }  // Function to handle right left case struct AVLwithparent* RLR(     struct AVLwithparent* root) {     root->right = LLR(root->right);     return RRR(root); }  // Function to insert a node in // the AVL tree struct AVLwithparent* Insert(     struct AVLwithparent* root,     struct AVLwithparent* parent,     int key) {      if (root == NULL) {          // Create and assign values         // to a new node         root = new struct AVLwithparent;          // If the root is NULL         if (root == NULL) {             cout << "Error in memory"                  << endl;         }          // Otherwise         else {             root->height = 1;             root->left = NULL;             root->right = NULL;             root->par = parent;             root->key = key;         }     }      else if (root->key > key) {          // Recur to the left subtree         // to insert the node         root->left = Insert(root->left,                             root, key);          // Store the heights of the         // left and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight                 - secondheight)             == 2) {              if (root->left != NULL                 && key < root->left->key) {                  // Left Left Case                 root = LLR(root);             }             else {                  // Left Right Case                 root = LRR(root);             }         }     }      else if (root->key < key) {          // Recur to the right subtree         // to insert the node         root->right = Insert(root->right,                              root, key);          // Store the heights of the         // left and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight                 = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight - secondheight) == 2) {             if (root->right != NULL                 && key < root->right->key) {                  // Right Left Case                 root = RLR(root);             }             else {                  // Right Right Case                 root = RRR(root);             }         }     }      // Case when given key is already     // in the tree     else {     }      // Update the height of the     // root node     Updateheight(root);      // Return the root node     return root; }  // Function to print the preorder // traversal of the AVL tree void printpreorder(     struct AVLwithparent* root) {     // Print the node's value along     // with its parent value     cout << "Node: " << root->key          << ", Parent Node: ";      if (root->par != NULL)         cout << root->par->key << endl;     else         cout << "NULL" << endl;      // Recur to the left subtree     if (root->left != NULL) {         printpreorder(root->left);     }      // Recur to the right subtree     if (root->right != NULL) {         printpreorder(root->right);     } }  // Driver Code int main() {     struct AVLwithparent* root;     root = NULL;      // Function Call to insert nodes     root = Insert(root, NULL, 10);     root = Insert(root, NULL, 20);     root = Insert(root, NULL, 30);     root = Insert(root, NULL, 40);     root = Insert(root, NULL, 50);     root = Insert(root, NULL, 25);      // Function call to print the tree     printpreorder(root); } 
Java
class AVLwithparent {     int key;     AVLwithparent left;     AVLwithparent right;     AVLwithparent par;     int height;      public AVLwithparent(int key) {         this.key = key;         this.left = null;         this.right = null;         this.par = null;         this.height = 1;     } }  public class AVLTreeWithParent {      // Function to update the height of a node based on its children's heights     public static void updateHeight(AVLwithparent root) {         if (root != null) {             int leftHeight = (root.left != null) ? root.left.height : 0;             int rightHeight = (root.right != null) ? root.right.height : 0;             root.height = Math.max(leftHeight, rightHeight) + 1;         }     }      // Left-Left Rotation (LLR) to balance the AVL tree     public static AVLwithparent LLR(AVLwithparent root) {         AVLwithparent tmpnode = root.left;         root.left = tmpnode.right;         if (tmpnode.right != null) {             tmpnode.right.par = root;         }         tmpnode.right = root;         tmpnode.par = root.par;         root.par = tmpnode;         if (tmpnode.par != null) {             if (root.key < tmpnode.par.key) {                 tmpnode.par.left = tmpnode;             } else {                 tmpnode.par.right = tmpnode;             }         }         updateHeight(root);         updateHeight(tmpnode);         return tmpnode;     }      // Right-Right Rotation (RRR) to balance the AVL tree     public static AVLwithparent RRR(AVLwithparent root) {         AVLwithparent tmpnode = root.right;         root.right = tmpnode.left;         if (tmpnode.left != null) {             tmpnode.left.par = root;         }         tmpnode.left = root;         tmpnode.par = root.par;         root.par = tmpnode;         if (tmpnode.par != null) {             if (root.key < tmpnode.par.key) {                 tmpnode.par.left = tmpnode;             } else {                 tmpnode.par.right = tmpnode;             }         }         updateHeight(root);         updateHeight(tmpnode);         return tmpnode;     }      // Left-Right Rotation (LRR) to balance the AVL tree     public static AVLwithparent LRR(AVLwithparent root) {         root.left = RRR(root.left);         return LLR(root);     }      // Right-Left Rotation (RLR) to balance the AVL tree     public static AVLwithparent RLR(AVLwithparent root) {         root.right = LLR(root.right);         return RRR(root);     }      // Function to insert a key into the AVL tree and balance the tree if needed     public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {         if (root == null) {             root = new AVLwithparent(key);             root.par = parent;         } else if (root.key > key) {             root.left = insert(root.left, root, key);             int leftHeight = (root.left != null) ? root.left.height : 0;             int rightHeight = (root.right != null) ? root.right.height : 0;             if (Math.abs(leftHeight - rightHeight) == 2) {                 if (key < root.left.key) {                     root = LLR(root);                 } else {                     root = LRR(root);                 }             }         } else if (root.key < key) {             root.right = insert(root.right, root, key);             int leftHeight = (root.left != null) ? root.left.height : 0;             int rightHeight = (root.right != null) ? root.right.height : 0;             if (Math.abs(leftHeight - rightHeight) == 2) {                 if (key < root.right.key) {                     root = RLR(root);                 } else {                     root = RRR(root);                 }             }         }         updateHeight(root);         return root;     }      // Function to print the nodes of the AVL tree in preorder     public static void printPreorder(AVLwithparent root) {         if (root != null) {             String parentKey = (root.par != null) ? Integer.toString(root.par.key) : "NULL";             System.out.println("Node: " + root.key + ", Parent Node: " + parentKey);             printPreorder(root.left);             printPreorder(root.right);         }     }      public static void main(String[] args) {         AVLwithparent root = null;         root = insert(root, null, 10);         root = insert(root, null, 20);         root = insert(root, null, 30);         root = insert(root, null, 40);         root = insert(root, null, 50);         root = insert(root, null, 25);         printPreorder(root);     } } 
Python
class AVLwithparent:     def __init__(self, key):         # Initialize a node with key, left and right child, parent, and height.         self.left = None         self.right = None         self.key = key         self.par = None         self.height = 1  # Function to update the height of a node based on its children's heights def update_height(root):     if root is not None:         left_height = root.left.height if root.left else 0  # Get the height of the left child         right_height = root.right.height if root.right else 0  # Get the height of the right child         root.height = max(left_height, right_height) + 1  # Update the height of the current node  # Left-Left Rotation (LLR) to balance the AVL tree def LLR(root):     # Perform a left rotation and then a right rotation     # to balance the tree when there's an imbalance in the left subtree     tmpnode = root.left     root.left = tmpnode.right     if tmpnode.right:         tmpnode.right.par = root     tmpnode.right = root     tmpnode.par = root.par     root.par = tmpnode     if tmpnode.par:         if root.key < tmpnode.par.key:             tmpnode.par.left = tmpnode         else:             tmpnode.par.right = tmpnode     update_height(root)     update_height(tmpnode)     return tmpnode  # Right-Right Rotation (RRR) to balance the AVL tree def RRR(root):     # Perform a right rotation and then a left rotation     # to balance the tree when there's an imbalance in the right subtree     tmpnode = root.right     root.right = tmpnode.left     if tmpnode.left:         tmpnode.left.par = root     tmpnode.left = root     tmpnode.par = root.par     root.par = tmpnode     if tmpnode.par:         if root.key < tmpnode.par.key:             tmpnode.par.left = tmpnode         else:             tmpnode.par.right = tmpnode     update_height(root)     update_height(tmpnode)     return tmpnode  # Left-Right Rotation (LRR) to balance the AVL tree def LRR(root):     # Perform a right rotation on the left child and then a left rotation on the root     root.left = RRR(root.left)     return LLR(root)  # Right-Left Rotation (RLR) to balance the AVL tree def RLR(root):     # Perform a left rotation on the right child and then a right rotation on the root     root.right = LLR(root.right)     return RRR(root)  # Function to insert a key into the AVL tree and balance the tree if needed def insert(root, parent, key):     if root is None:         root = AVLwithparent(key)  # Create a new node if the current node is None         root.par = parent  # Set the parent of the new node     elif root.key > key:         # Insert the key into the left subtree and balance the tree if needed         root.left = insert(root.left, root, key)         left_height = root.left.height if root.left else 0         right_height = root.right.height if root.right else 0         if abs(left_height - right_height) == 2:             if key < root.left.key:                 root = LLR(root)             else:                 root = LRR(root)     elif root.key < key:         # Insert the key into the right subtree and balance the tree if needed         root.right = insert(root.right, root, key)         left_height = root.left.height if root.left else 0         right_height = root.right.height if root.right else 0         if abs(left_height - right_height) == 2:             if key < root.right.key:                 root = RLR(root)             else:                 root = RRR(root)     update_height(root)  # Update the height of the current node after insertion     return root  # Return the root of the updated subtree  # Function to print the nodes of the AVL tree in preorder def print_preorder(root):     if root:         parent_key = root.par.key if root.par else "NULL"  # Get the key of the parent node or "NULL" if it's None         print(f"Node: {root.key}, Parent Node: {parent_key}")  # Print the node and its parent         print_preorder(root.left)  # Print the left subtree in preorder         print_preorder(root.right)  # Print the right subtree in preorder  # Main function to demonstrate AVL tree operations if __name__ == "__main__":     root = None  # Initialize the root of the AVL tree as None     # Insert keys into the AVL tree     root = insert(root, None, 10)     root = insert(root, None, 20)     root = insert(root, None, 30)     root = insert(root, None, 40)     root = insert(root, None, 50)     root = insert(root, None, 25)     # Print the AVL tree in preorder     print_preorder(root) 
C#
using System;  public class AVLwithparent {     public AVLwithparent left;     public AVLwithparent right;     public int key;     public AVLwithparent par;     public int height; }  public class Program {     public static void UpdateHeight(AVLwithparent root)     {         if (root != null)         {             int val = 1;              if (root.left != null)                 val = root.left.height + 1;              if (root.right != null)                 val = Math.Max(val, root.right.height + 1);              root.height = val;         }     }      public static AVLwithparent LLR(AVLwithparent root)     {         AVLwithparent tmpNode = root.left;          root.left = tmpNode.right;          if (tmpNode.right != null)             tmpNode.right.par = root;          tmpNode.right = root;          tmpNode.par = root.par;          root.par = tmpNode;          if (tmpNode.par != null && root.key < tmpNode.par.key)         {             tmpNode.par.left = tmpNode;         }         else         {             if (tmpNode.par != null)                 tmpNode.par.right = tmpNode;         }          root = tmpNode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      public static AVLwithparent RRR(AVLwithparent root)     {         AVLwithparent tmpNode = root.right;          root.right = tmpNode.left;          if (tmpNode.left != null)             tmpNode.left.par = root;          tmpNode.left = root;          tmpNode.par = root.par;          root.par = tmpNode;          if (tmpNode.par != null && root.key < tmpNode.par.key)         {             tmpNode.par.left = tmpNode;         }         else         {             if (tmpNode.par != null)                 tmpNode.par.right = tmpNode;         }          root = tmpNode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      public static AVLwithparent LRR(AVLwithparent root)     {         root.left = RRR(root.left);         return LLR(root);     }      public static AVLwithparent RLR(AVLwithparent root)     {         root.right = LLR(root.right);         return RRR(root);     }      public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)     {         if (root == null)         {             root = new AVLwithparent             {                 height = 1,                 left = null,                 right = null,                 par = parent,                 key = key             };         }         else if (root.key > key)         {             root.left = Insert(root.left, root, key);              int firstHeight = 0;             int secondHeight = 0;              if (root.left != null)                 firstHeight = root.left.height;              if (root.right != null)                 secondHeight = root.right.height;              if (Math.Abs(firstHeight - secondHeight) == 2)             {                 if (root.left != null && key < root.left.key)                 {                     root = LLR(root);                 }                 else                 {                     root = LRR(root);                 }             }         }         else if (root.key < key)         {             root.right = Insert(root.right, root, key);              int firstHeight = 0;             int secondHeight = 0;              if (root.left != null)                 firstHeight = root.left.height;              if (root.right != null)                 secondHeight = root.right.height;              if (Math.Abs(firstHeight - secondHeight) == 2)             {                 if (root.right != null && key < root.right.key)                 {                     root = RLR(root);                 }                 else                 {                     root = RRR(root);                 }             }         }         else         {             // Case when given key is already in the tree         }          UpdateHeight(root);          return root;     }      public static void PrintPreorder(AVLwithparent root)     {         Console.Write("Node: " + root.key + ", Parent Node: ");         if (root.par != null)             Console.WriteLine(root.par.key);         else             Console.WriteLine("NULL");          if (root.left != null)         {             PrintPreorder(root.left);         }          if (root.right != null)         {             PrintPreorder(root.right);         }     }      public static void Main()     {         AVLwithparent root = null;          root = Insert(root, null, 10);         root = Insert(root, null, 20);         root = Insert(root, null, 30);         root = Insert(root, null, 40);         root = Insert(root, null, 50);         root = Insert(root, null, 25);          PrintPreorder(root);     } } 
JavaScript
class AVLwithparent {     constructor(key) {         this.key = key;         this.left = null;         this.right = null;         this.par = null;         this.height = 1;     } }  // Function to update the height of a node based on its children's heights function updateHeight(root) {     if (root !== null) {         const leftHeight = (root.left !== null) ? root.left.height : 0;         const rightHeight = (root.right !== null) ? root.right.height : 0;         root.height = Math.max(leftHeight, rightHeight) + 1;     } }  // Left-Left Rotation (LLR) to balance the AVL tree function LLR(root) {     const tmpnode = root.left;     root.left = tmpnode.right;     if (tmpnode.right !== null) {         tmpnode.right.par = root;     }     tmpnode.right = root;     tmpnode.par = root.par;     root.par = tmpnode;     if (tmpnode.par !== null) {         if (root.key < tmpnode.par.key) {             tmpnode.par.left = tmpnode;         } else {             tmpnode.par.right = tmpnode;         }     }     updateHeight(root);     updateHeight(tmpnode);     return tmpnode; }  // Right-Right Rotation (RRR) to balance the AVL tree function RRR(root) {     const tmpnode = root.right;     root.right = tmpnode.left;     if (tmpnode.left !== null) {         tmpnode.left.par = root;     }     tmpnode.left = root;     tmpnode.par = root.par;     root.par = tmpnode;     if (tmpnode.par !== null) {         if (root.key < tmpnode.par.key) {             tmpnode.par.left = tmpnode;         } else {             tmpnode.par.right = tmpnode;         }     }     updateHeight(root);     updateHeight(tmpnode);     return tmpnode; }  // Left-Right Rotation (LRR) to balance the AVL tree function LRR(root) {     root.left = RRR(root.left);     return LLR(root); }  // Right-Left Rotation (RLR) to balance the AVL tree function RLR(root) {     root.right = LLR(root.right);     return RRR(root); }  // Function to insert a key into the AVL tree and balance the tree if needed function insert(root, parent, key) {     if (root === null) {         root = new AVLwithparent(key);         root.par = parent;     } else if (root.key > key) {         root.left = insert(root.left, root, key);         const leftHeight = (root.left !== null) ? root.left.height : 0;         const rightHeight = (root.right !== null) ? root.right.height : 0;         if (Math.abs(leftHeight - rightHeight) === 2) {             if (key < root.left.key) {                 root = LLR(root);             } else {                 root = LRR(root);             }         }     } else if (root.key < key) {         root.right = insert(root.right, root, key);         const leftHeight = (root.left !== null) ? root.left.height : 0;         const rightHeight = (root.right !== null) ? root.right.height : 0;         if (Math.abs(leftHeight - rightHeight) === 2) {             if (key < root.right.key) {                 root = RLR(root);             } else {                 root = RRR(root);             }         }     }     updateHeight(root);     return root; }  // Function to print the nodes of the AVL tree in preorder function printPreorder(root) {     if (root !== null) {         const parentKey = (root.par !== null) ? root.par.key : "NULL";         console.log(`Node: ${root.key}, Parent Node: ${parentKey}`);         printPreorder(root.left);         printPreorder(root.right);     } }  // Example usage let root = null; root = insert(root, null, 10); root = insert(root, null, 20); root = insert(root, null, 30); root = insert(root, null, 40); root = insert(root, null, 50); root = insert(root, null, 25); printPreorder(root); 

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:

  • Start from the root node.
  • If the root node is NULL, return false.
  • Check if the current node’s value is equal to the value of the node to be searched. If yes, return true.
  • If the current node’s value is less than searched key then recur to the right subtree.
  • If the current node’s value is greater than searched key then recur to the left subtree.

Below is the implementation of the above approach:

C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;  // AVL tree node struct AVLwithparent {     struct AVLwithparent* left;     struct AVLwithparent* right;     int key;     struct AVLwithparent* par;     int height; };  // Function to update the height of // a node according to its children's // node's heights void Updateheight(struct AVLwithparent* root) {     if (root != NULL) {          // Store the height of the         // current node         int val = 1;          // Store the height of the left         // and the right subtree         if (root->left != NULL)             val = root->left->height + 1;          if (root->right != NULL)             val = max(                 val, root->right->height + 1);          // Update the height of the         // current node         root->height = val;     } }  // Function to handle Left Left Case struct AVLwithparent* LLR(     struct AVLwithparent* root) {     // Create a reference to the     // left child     struct AVLwithparent* tmpnode = root->left;      // Update the left child of the     // root to the right child of the     // current left child of the root     root->left = tmpnode->right;      // Update parent pointer of the left     // child of the root node     if (tmpnode->right != NULL)         tmpnode->right->par = root;      // Update the right child of     // tmpnode to root     tmpnode->right = root;      // Update parent pointer of tmpnode     tmpnode->par = root->par;      // Update the parent pointer of root     root->par = tmpnode;      // Update tmpnode as the left or     // the right child of its parent     // pointer according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Right Right Case struct AVLwithparent* RRR(     struct AVLwithparent* root) {     // Create a reference to the     // right child     struct AVLwithparent* tmpnode = root->right;      // Update the right child of the     // root as the left child of the     // current right child of the root     root->right = tmpnode->left;      // Update parent pointer of the right     // child of the root node     if (tmpnode->left != NULL)         tmpnode->left->par = root;      // Update the left child of the     // tmpnode to root     tmpnode->left = root;      // Update parent pointer of tmpnode     tmpnode->par = root->par;      // Update the parent pointer of root     root->par = tmpnode;      // Update tmpnode as the left or     // the right child of its parent     // pointer according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Left Right Case struct AVLwithparent* LRR(     struct AVLwithparent* root) {     root->left = RRR(root->left);     return LLR(root); }  // Function to handle right left case struct AVLwithparent* RLR(     struct AVLwithparent* root) {     root->right = LLR(root->right);     return RRR(root); }  // Function to insert a node in // the AVL tree struct AVLwithparent* Insert(     struct AVLwithparent* root,     struct AVLwithparent* parent,     int key) {      if (root == NULL) {          // Create and assign values         // to a new node         root = new struct AVLwithparent;         if (root == NULL) {             cout << "Error in memory" << endl;         }          // Otherwise         else {             root->height = 1;             root->left = NULL;             root->right = NULL;             root->par = parent;             root->key = key;         }     }      else if (root->key > key) {          // Recur to the left subtree         // to insert the node         root->left = Insert(root->left,                             root, key);          // Stores the heights of the         // left and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight                 - secondheight)             == 2) {              if (root->left != NULL                 && key < root->left->key) {                  // Left Left Case                 root = LLR(root);             }             else {                  // Left Right Case                 root = LRR(root);             }         }     }      else if (root->key < key) {          // Recur to the right subtree         // to insert the node         root->right = Insert(root->right, root, key);          // Store the heights of the left         // and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight                 - secondheight)             == 2) {             if (root->right != NULL                 && key < root->right->key) {                  // Right Left Case                 root = RLR(root);             }             else {                  // Right Right Case                 root = RRR(root);             }         }     }      // Case when given key is     // already in tree     else {     }      // Update the height of the     // root node     Updateheight(root);      // Return the root node     return root; }  // Function to find a key in AVL tree bool AVLsearch(     struct AVLwithparent* root, int key) {     // If root is NULL     if (root == NULL)         return false;      // If found, return true     else if (root->key == key)         return true;      // Recur to the left subtree if     // the current node's value is     // greater than key     else if (root->key > key) {         bool val = AVLsearch(root->left, key);         return val;     }      // Otherwise, recur to the     // right subtree     else {         bool val = AVLsearch(root->right, key);         return val;     } }  // Driver Code int main() {     struct AVLwithparent* root;     root = NULL;      // Function call to insert the nodes     root = Insert(root, NULL, 10);     root = Insert(root, NULL, 20);     root = Insert(root, NULL, 30);     root = Insert(root, NULL, 40);     root = Insert(root, NULL, 50);     root = Insert(root, NULL, 25);      // Function call to search for a node     bool found = AVLsearch(root, 40);     if (found)         cout << "value found";     else         cout << "value not found";      return 0; } 
Java
class AVLwithparent {     AVLwithparent left, right, par;     int key;     int height;      // Constructor     public AVLwithparent(int key, AVLwithparent parent) {         this.key = key;         this.par = parent;         this.height = 1;     } }  public class AVLTree {     // Function to update the height of a node according to its children's node's heights     public static void updateHeight(AVLwithparent root) {         if (root != null) {             int val = 1;              if (root.left != null)                 val = root.left.height + 1;              if (root.right != null)                 val = Math.max(val, root.right.height + 1);              root.height = val;         }     }      // Function to handle Left Left Case     public static AVLwithparent llr(AVLwithparent root) {         AVLwithparent tmpnode = root.left;          root.left = tmpnode.right;          if (tmpnode.right != null)             tmpnode.right.par = root;          tmpnode.right = root;          tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root = tmpnode;          updateHeight(root.left);         updateHeight(root.right);         updateHeight(root);         updateHeight(root.par);          return root;     }      // Function to handle Right Right Case     public static AVLwithparent rrr(AVLwithparent root) {         AVLwithparent tmpnode = root.right;          root.right = tmpnode.left;          if (tmpnode.left != null)             tmpnode.left.par = root;          tmpnode.left = root;          tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root = tmpnode;          updateHeight(root.left);         updateHeight(root.right);         updateHeight(root);         updateHeight(root.par);          return root;     }      // Function to handle Left Right Case     public static AVLwithparent lrr(AVLwithparent root) {         root.left = rrr(root.left);         return llr(root);     }      // Function to handle right left case     public static AVLwithparent rlr(AVLwithparent root) {         root.right = llr(root.right);         return rrr(root);     }      // Function to insert a node in the AVL tree     public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {         if (root == null) {             root = new AVLwithparent(key, parent);         } else if (root.key > key) {             root.left = insert(root.left, root, key);              int firstHeight = (root.left != null) ? root.left.height : 0;             int secondHeight = (root.right != null) ? root.right.height : 0;              if (Math.abs(firstHeight - secondHeight) == 2) {                 if (root.left != null && key < root.left.key)                     root = llr(root);                 else                     root = lrr(root);             }         } else if (root.key < key) {             root.right = insert(root.right, root, key);              int firstHeight = (root.left != null) ? root.left.height : 0;             int secondHeight = (root.right != null) ? root.right.height : 0;              if (Math.abs(firstHeight - secondHeight) == 2) {                 if (root.right != null && key < root.right.key)                     root = rlr(root);                 else                     root = rrr(root);             }         }          updateHeight(root);         return root;     }      // Function to find a key in AVL tree     public static boolean avlSearch(AVLwithparent root, int key) {         if (root == null)             return false;         else if (root.key == key)             return true;         else if (root.key > key)             return avlSearch(root.left, key);         else             return avlSearch(root.right, key);     }      // Driver Code     public static void main(String[] args) {         AVLwithparent root = null;          root = insert(root, null, 10);         root = insert(root, null, 20);         root = insert(root, null, 30);         root = insert(root, null, 40);         root = insert(root, null, 50);         root = insert(root, null, 25);          boolean found = avlSearch(root, 40);          if (found)             System.out.println("Value found");         else             System.out.println("Value not found");     } } 
Python
# Python program for the above approach  # AVL tree node class AVLwithparent:     def __init__(self, key, parent=None):         self.left = None         self.right = None         self.key = key         self.par = parent         self.height = 1  # Function to update the height of # a node according to its children's # node's heights def update_height(root):     if root is not None:          # Store the height of the         # current node         val = 1          # Store the height of the left         # and the right subtree         if root.left is not None:             val = root.left.height + 1          if root.right is not None:             val = max(val, root.right.height + 1)          # Update the height of the         # current node         root.height = val  # Function to handle Left Left Case def llr(root):     # Create a reference to the     # left child     tmp_node = root.left      # Update the left child of the     # root to the right child of the     # current left child of the root     root.left = tmp_node.right      # Update parent pointer of the left     # child of the root node     if tmp_node.right is not None:         tmp_node.right.par = root      # Update the right child of     # tmp_node to root     tmp_node.right = root      # Update parent pointer of tmp_node     tmp_node.par = root.par      # Update the parent pointer of root     root.par = tmp_node      # Update tmp_node as the left or     # the right child of its parent     # pointer according to its key value     if tmp_node.par is not None and root.key < tmp_node.par.key:         tmp_node.par.left = tmp_node     else:         if tmp_node.par is not None:             tmp_node.par.right = tmp_node      # Make tmp_node as the new root     root = tmp_node      # Update the heights     update_height(root.left)     update_height(root.right)     update_height(root)     update_height(root.par)      # Return the root node     return root  # Function to handle Right Right Case def rrr(root):     # Create a reference to the     # right child     tmp_node = root.right      # Update the right child of the     # root as the left child of the     # current right child of the root     root.right = tmp_node.left      # Update parent pointer of the right     # child of the root node     if tmp_node.left is not None:         tmp_node.left.par = root      # Update the left child of the     # tmp_node to root     tmp_node.left = root      # Update parent pointer of tmp_node     tmp_node.par = root.par      # Update the parent pointer of root     root.par = tmp_node      # Update tmp_node as the left or     # the right child of its parent     # pointer according to its key value     if tmp_node.par is not None and root.key < tmp_node.par.key:         tmp_node.par.left = tmp_node     else:         if tmp_node.par is not None:             tmp_node.par.right = tmp_node      # Make tmp_node as the new root     root = tmp_node      # Update the heights     update_height(root.left)     update_height(root.right)     update_height(root)     update_height(root.par)      # Return the root node     return root  # Function to handle Left Right Case def lrr(root):     root.left = rrr(root.left)     return llr(root)  # Function to handle Right Left Case def rlr(root):     root.right = llr(root.right)     return rrr(root)  # Function to insert a node in # the AVL tree def insert(root, parent, key):     if root is None:          # Create and assign values         # to a new node         root = AVLwithparent(key, parent)      else:         if root.key > key:              # Recur to the left subtree             # to insert the node             root.left = insert(root.left, root, key)              # Stores the heights of the             # left and right subtree             first_height = 0             second_height = 0              if root.left is not None:                 first_height = root.left.height              if root.right is not None:                 second_height = root.right.height              # Balance the tree if the             # current node is not balanced             if abs(first_height - second_height) == 2:                  if root.left is not None and key < root.left.key:                      # Left Left Case                     root = llr(root)                 else:                      # Left Right Case                     root = lrr(root)          elif root.key < key:              # Recur to the right subtree             # to insert the node             root.right = insert(root.right, root, key)              # Store the heights of the left             # and right subtree             first_height = 0             second_height = 0              if root.left is not None:                 first_height = root.left.height              if root.right is not None:                 second_height = root.right.height              # Balance the tree if the             # current node is not balanced             if abs(first_height - second_height) == 2:                 if root.right is not None and key < root.right.key:                      # Right Left Case                     root = rlr(root)                 else:                      # Right Right Case                     root = rrr(root)      # Update the height of the     # root node     update_height(root)      # Return the root node     return root  # Function to find a key in AVL tree def avl_search(root, key):     # If root is None     if root is None:         return False      # If found, return True     elif root.key == key:         return True      # Recur to the left subtree if     # the current node's value is     # greater than key     elif root.key > key:         return avl_search(root.left, key)      # Otherwise, recur to the     # right subtree     else:         return avl_search(root.right, key)  # Driver Code if __name__ == "__main__":     root = None      # Function call to insert the nodes     root = insert(root, None, 10)     root = insert(root, None, 20)     root = insert(root, None, 30)     root = insert(root, None, 40)     root = insert(root, None, 50)     root = insert(root, None, 25)      # Function call to search for a node     found = avl_search(root, 40)     if found:         print("Value found")     else:         print("Value not found") 
C#
using System;  // AVL tree node public class AVLwithparent {     public AVLwithparent left;     public AVLwithparent right;     public int key;     public AVLwithparent par;     public int height; }  public class AVLTree {     // Function to update the height of a node according to its children's node's heights     public static void UpdateHeight(AVLwithparent root)     {         if (root != null)         {             int val = 1;              if (root.left != null)                 val = root.left.height + 1;              if (root.right != null)                 val = Math.Max(val, root.right.height + 1);              root.height = val;         }     }      // Function to handle Left Left Case     public static AVLwithparent LLR(AVLwithparent root)     {         AVLwithparent tmpnode = root.left;          root.left = tmpnode.right;          if (tmpnode.right != null)             tmpnode.right.par = root;          tmpnode.right = root;          tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else         {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root = tmpnode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      // Function to handle Right Right Case     public static AVLwithparent RRR(AVLwithparent root)     {         AVLwithparent tmpnode = root.right;          root.right = tmpnode.left;          if (tmpnode.left != null)             tmpnode.left.par = root;          tmpnode.left = root;          tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else         {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root = tmpnode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      // Function to handle Left Right Case     public static AVLwithparent LRR(AVLwithparent root)     {         root.left = RRR(root.left);         return LLR(root);     }      // Function to handle right left case     public static AVLwithparent RLR(AVLwithparent root)     {         root.right = LLR(root.right);         return RRR(root);     }      // Function to insert a node in the AVL tree     public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)     {         if (root == null)         {             root = new AVLwithparent();             root.height = 1;             root.left = null;             root.right = null;             root.par = parent;             root.key = key;         }         else if (root.key > key)         {             root.left = Insert(root.left, root, key);              int firstHeight = 0;             int secondHeight = 0;              if (root.left != null)                 firstHeight = root.left.height;              if (root.right != null)                 secondHeight = root.right.height;              if (Math.Abs(firstHeight - secondHeight) == 2)             {                 if (root.left != null && key < root.left.key)                     root = LLR(root);                 else                     root = LRR(root);             }         }         else if (root.key < key)         {             root.right = Insert(root.right, root, key);              int firstHeight = 0;             int secondHeight = 0;              if (root.left != null)                 firstHeight = root.left.height;              if (root.right != null)                 secondHeight = root.right.height;              if (Math.Abs(firstHeight - secondHeight) == 2)             {                 if (root.right != null && key < root.right.key)                     root = RLR(root);                 else                     root = RRR(root);             }         }          UpdateHeight(root);          return root;     }      // Function to find a key in AVL tree     public static bool AVLSearch(AVLwithparent root, int key)     {         if (root == null)             return false;         else if (root.key == key)             return true;         else if (root.key > key)             return AVLSearch(root.left, key);         else             return AVLSearch(root.right, key);     }      // Driver Code     public static void Main(string[] args)     {         AVLwithparent root = null;          root = Insert(root, null, 10);         root = Insert(root, null, 20);         root = Insert(root, null, 30);         root = Insert(root, null, 40);         root = Insert(root, null, 50);         root = Insert(root, null, 25);          bool found = AVLSearch(root, 40);          if (found)             Console.WriteLine("Value found");         else             Console.WriteLine("Value not found");     } } 
JavaScript
class AVLwithparent {     constructor(key, parent = null) {         this.left = null;         this.right = null;         this.key = key;         this.par = parent; // 'par' keeps track of the parent node         this.height = 1; // Height of the node initialized to 1     } }  // Function to update the height of a node function updateHeight(root) {     if (root !== null) {         let val = 1;          if (root.left !== null) {             val = root.left.height + 1; // Update height considering the left subtree         }          if (root.right !== null) {             val = Math.max(val, root.right.height + 1); // Update height considering the right subtree         }          root.height = val; // Update the height of the current node     } }  // Left-Left Rotation (LLR) function llr(root) {     let tmpNode = root.left;      root.left = tmpNode.right;     if (tmpNode.right !== null) {         tmpNode.right.par = root;     }      tmpNode.right = root;     tmpNode.par = root.par;     root.par = tmpNode;      if (tmpNode.par !== null && root.key < tmpNode.par.key) {         tmpNode.par.left = tmpNode;     } else {         if (tmpNode.par !== null) {             tmpNode.par.right = tmpNode;         }     }      root = tmpNode;      // Update heights after rotation     updateHeight(root.left);     updateHeight(root.right);     updateHeight(root);     updateHeight(root.par);      return root; }  // Right-Right Rotation (RRR) function rrr(root) {     let tmpNode = root.right;      root.right = tmpNode.left;     if (tmpNode.left !== null) {         tmpNode.left.par = root;     }      tmpNode.left = root;     tmpNode.par = root.par;     root.par = tmpNode;      if (tmpNode.par !== null && root.key < tmpNode.par.key) {         tmpNode.par.left = tmpNode;     } else {         if (tmpNode.par !== null) {             tmpNode.par.right = tmpNode;         }     }      root = tmpNode;      // Update heights after rotation     updateHeight(root.left);     updateHeight(root.right);     updateHeight(root);     updateHeight(root.par);      return root; }  // Left-Right Rotation (LRR) function lrr(root) {     root.left = rrr(root.left);     return llr(root); }  // Right-Left Rotation (RLR) function rlr(root) {     root.right = llr(root.right);     return rrr(root); }  // Function to insert a node into the AVL tree function insert(root, parent, key) {     if (root === null) {         root = new AVLwithparent(key, parent);     } else {         if (root.key > key) {             root.left = insert(root.left, root, key);             // Perform rotations if necessary after insertion             let firstHeight = root.left ? root.left.height : 0;             let secondHeight = root.right ? root.right.height : 0;              if (Math.abs(firstHeight - secondHeight) === 2) {                 if (root.left !== null && key < root.left.key) {                     root = llr(root);                 } else {                     root = lrr(root);                 }             }         } else if (root.key < key) {             root.right = insert(root.right, root, key);             // Perform rotations if necessary after insertion             let firstHeight = root.left ? root.left.height : 0;             let secondHeight = root.right ? root.right.height : 0;              if (Math.abs(firstHeight - secondHeight) === 2) {                 if (root.right !== null && key < root.right.key) {                     root = rlr(root);                 } else {                     root = rrr(root);                 }             }         }     }      updateHeight(root); // Update the height of the current node     return root; }  // Function to search for a node in the AVL tree function avlSearch(root, key) {     if (root === null) {         return false;     } else if (root.key === key) {         return true;     } else if (root.key > key) {         return avlSearch(root.left, key);     } else {         return avlSearch(root.right, key);     } }  // Driver Code let root = null;  // Inserting nodes into the AVL tree root = insert(root, null, 10); root = insert(root, null, 20); root = insert(root, null, 30); root = insert(root, null, 40); root = insert(root, null, 50); root = insert(root, null, 25);  // Searching for a value in the AVL tree let found = avlSearch(root, 40); if (found) {     console.log("Value found"); } else {     console.log("Value not found"); } 

Output
value found

Time Complexity: O(log N), where N is the number of nodes of the tree
Auxiliary Space: O(1)

Delete Operation: The deletion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the references to the parent pointers need to be updated with every deletion and rotation accordingly. Follow the steps below to perform the delete operation:

  • Perform the delete procedure as in a normal BST.
  • From the node that has been deleted, move towards the root.
  • At each node on the path, update the height of the node.
  • Check for AVL conditions at each node. Let there be 3 nodes: w, x, y where w is the current node, x is the root of the subtree of w which has greater height and y is the root of the subtree of x which has greater height.
  • If the node w is unbalanced, there exists one of the following 4 cases:
    • Left Left Case (x is left child of w and y is left child of x)
    • Left Right Case (x is left child of w and y is right child of x)
    • Right Left Case (x is right child of w and y is left child of x)
    • Right Right Case (x is right child of w and y is right child of x)

Below is the implementation of the above approach:

C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;  // AVL tree node struct AVLwithparent {     struct AVLwithparent* left;     struct AVLwithparent* right;     int key;     struct AVLwithparent* par;     int height; };  // Function to print the preorder // traversal of the AVL tree void printpreorder(struct AVLwithparent* root) {     // Print the node's value along     // with its parent value     cout << "Node: " << root->key          << ", Parent Node: ";      if (root->par != NULL)         cout << root->par->key << endl;     else         cout << "NULL" << endl;      // Recur to the left subtree     if (root->left != NULL) {         printpreorder(root->left);     }      // Recur to the right subtree     if (root->right != NULL) {         printpreorder(root->right);     } }  // Function to update the height of // a node according to its children's // node's heights void Updateheight(     struct AVLwithparent* root) {     if (root != NULL) {          // Store the height of the         // current node         int val = 1;          // Store the height of the left         // and right subtree         if (root->left != NULL)             val = root->left->height + 1;          if (root->right != NULL)             val = max(                 val, root->right->height + 1);          // Update the height of the         // current node         root->height = val;     } }  // Function to handle Left Left Case struct AVLwithparent* LLR(     struct AVLwithparent* root) {     // Create a reference to the     // left child     struct AVLwithparent* tmpnode = root->left;      // Update the left child of the     // root to the right child of the     // current left child of the root     root->left = tmpnode->right;      // Update parent pointer of left     // child of the root node     if (tmpnode->right != NULL)         tmpnode->right->par = root;      // Update the right child of     // tmpnode to root     tmpnode->right = root;      // Update parent pointer of tmpnode     tmpnode->par = root->par;      // Update the parent pointer of root     root->par = tmpnode;      // Update tmpnode as the left or     // the right child of its parent     // pointer according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Right Right Case struct AVLwithparent* RRR(     struct AVLwithparent* root) {     // Create a reference to the     // right child     struct AVLwithparent* tmpnode = root->right;      // Update the right child of the     // root as the left child of the     // current right child of the root     root->right = tmpnode->left;      // Update parent pointer of the     // right child of the root node     if (tmpnode->left != NULL)         tmpnode->left->par = root;      // Update the left child of the     // tmpnode to root     tmpnode->left = root;      // Update parent pointer of tmpnode     tmpnode->par = root->par;      // Update the parent pointer of root     root->par = tmpnode;      // Update tmpnode as the left or     // the right child of its parent     // pointer according to its key value     if (tmpnode->par != NULL         && root->key < tmpnode->par->key) {         tmpnode->par->left = tmpnode;     }     else {         if (tmpnode->par != NULL)             tmpnode->par->right = tmpnode;     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root->left);     Updateheight(root->right);     Updateheight(root);     Updateheight(root->par);      // Return the root node     return root; }  // Function to handle Left Right Case struct AVLwithparent* LRR(     struct AVLwithparent* root) {     root->left = RRR(root->left);     return LLR(root); }  // Function to handle right left case struct AVLwithparent* RLR(     struct AVLwithparent* root) {     root->right = LLR(root->right);     return RRR(root); }  // Function to balance the tree after // deletion of a node struct AVLwithparent* Balance(     struct AVLwithparent* root) {     // Store the current height of     // the left and right subtree     int firstheight = 0;     int secondheight = 0;      if (root->left != NULL)         firstheight = root->left->height;      if (root->right != NULL)         secondheight = root->right->height;      // If current node is not balanced     if (abs(firstheight - secondheight) == 2) {         if (firstheight < secondheight) {              // Store the height of the             // left and right subtree             // of the current node's             // right subtree             int rightheight1 = 0;             int rightheight2 = 0;             if (root->right->right != NULL)                 rightheight2 = root->right->right->height;              if (root->right->left != NULL)                 rightheight1 = root->right->left->height;              if (rightheight1 > rightheight2) {                  // Right Left Case                 root = RLR(root);             }             else {                  // Right Right Case                 root = RRR(root);             }         }         else {              // Store the height of the             // left and right subtree             // of the current node's             // left subtree             int leftheight1 = 0;             int leftheight2 = 0;             if (root->left->right != NULL)                 leftheight2 = root->left->right->height;              if (root->left->left != NULL)                 leftheight1 = root->left->left->height;              if (leftheight1 > leftheight2) {                  // Left Left Case                 root = LLR(root);             }             else {                  // Left Right Case                 root = LRR(root);             }         }     }      // Return the root node     return root; }  // Function to insert a node in // the AVL tree struct AVLwithparent* Insert(     struct AVLwithparent* root,     struct AVLwithparent* parent,     int key) {      if (root == NULL) {          // Create and assign values         // to a new node         root = new struct AVLwithparent;         if (root == NULL)             cout << "Error in memory" << endl;         else {             root->height = 1;             root->left = NULL;             root->right = NULL;             root->par = parent;             root->key = key;         }     }      else if (root->key > key) {          // Recur to the left subtree         // to insert the node         root->left = Insert(root->left,                             root, key);          // Store the heights of the         // left and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight                 - secondheight)             == 2) {              if (root->left != NULL                 && key < root->left->key) {                  // Left Left Case                 root = LLR(root);             }             else {                  // Left Right Case                 root = LRR(root);             }         }     }      else if (root->key < key) {          // Recur to the right subtree         // to insert the node         root->right = Insert(root->right,                              root, key);          // Store the heights of the left         // and right subtree         int firstheight = 0;         int secondheight = 0;          if (root->left != NULL)             firstheight = root->left->height;          if (root->right != NULL)             secondheight = root->right->height;          // Balance the tree if the         // current node is not balanced         if (abs(firstheight - secondheight) == 2) {             if (root->right != NULL                 && key < root->right->key) {                  // Right Left Case                 root = RLR(root);             }             else {                  // Right Right Case                 root = RRR(root);             }         }     }      // Case when given key is     // already in tree     else {     }      // Update the height of the     // root node     Updateheight(root);      // Return the root node     return root; }  // Function to delete a node from // the AVL tree struct AVLwithparent* Delete(     struct AVLwithparent* root,     int key) {     if (root != NULL) {          // If the node is found         if (root->key == key) {              // Replace root with its             // left child             if (root->right == NULL                 && root->left != NULL) {                 if (root->par != NULL) {                     if (root->par->key                         < root->key)                         root->par->right = root->left;                     else                         root->par->left = root->left;                      // Update the height                     // of root's parent                     Updateheight(root->par);                 }                  root->left->par = root->par;                  // Balance the node                 // after deletion                 root->left = Balance(                     root->left);                  return root->left;             }              // Replace root with its             // right child             else if (root->left == NULL                      && root->right != NULL) {                 if (root->par != NULL) {                     if (root->par->key                         < root->key)                         root->par->right = root->right;                     else                         root->par->left = root->right;                      // Update the height                     // of the root's parent                     Updateheight(root->par);                 }                  root->right->par = root->par;                  // Balance the node after                 // deletion                 root->right = Balance(root->right);                 return root->right;             }              // Remove the references of             // the current node             else if (root->left == NULL                      && root->right == NULL) {                 if (root->par->key < root->key) {                     root->par->right = NULL;                 }                 else {                     root->par->left = NULL;                 }                  if (root->par != NULL)                     Updateheight(root->par);                  root = NULL;                 return NULL;             }              // Otherwise, replace the             // current node with its             // successor and then             // recursively call Delete()             else {                 struct AVLwithparent* tmpnode = root;                 tmpnode = tmpnode->right;                 while (tmpnode->left != NULL) {                     tmpnode = tmpnode->left;                 }                  int val = tmpnode->key;                  root->right                     = Delete(root->right, tmpnode->key);                  root->key = val;                  // Balance the node                 // after deletion                 root = Balance(root);             }         }          // Recur to the right subtree to         // delete the current node         else if (root->key < key) {             root->right = Delete(root->right, key);              root = Balance(root);         }          // Recur into the right subtree         // to delete the current node         else if (root->key > key) {             root->left = Delete(root->left, key);              root = Balance(root);         }          // Update height of the root         if (root != NULL) {             Updateheight(root);         }     }      // Handle the case when the key to be     // deleted could not be found     else {         cout << "Key to be deleted "              << "could not be found\n";     }      // Return the root node     return root; }  // Driver Code int main() {     struct AVLwithparent* root;     root = NULL;      // Function call to insert the nodes     root = Insert(root, NULL, 9);     root = Insert(root, NULL, 5);     root = Insert(root, NULL, 10);     root = Insert(root, NULL, 0);     root = Insert(root, NULL, 6);      // Print the tree before deleting node     cout << "Before deletion:\n";     printpreorder(root);      // Function Call to delete node 10     root = Delete(root, 10);      // Print the tree after deleting node     cout << "After deletion:\n";     printpreorder(root); } 
Java
// Java program for the above approach class AVLwithparent {     AVLwithparent left, right, par;     int key, height;      AVLwithparent(int item) {         key = item;         height = 1;     } }  public class AVLTreeWithParent {      // Function to print the preorder     // traversal of the AVL tree     static void printPreorder(AVLwithparent root) {         if (root != null) {             // Print the node's value along             // with its parent value             System.out.print("Node: " + root.key + ", Parent Node: ");              if (root.par != null)                 System.out.println(root.par.key);             else                 System.out.println("NULL");              // Recur to the left subtree             printPreorder(root.left);              // Recur to the right subtree             printPreorder(root.right);         }     }      // Function to update the height of     // a node according to its children's     // node's heights     static void updateHeight(AVLwithparent root) {         if (root != null) {             // Store the height of the             // current node             int val = 1;              // Store the height of the left             // and right subtree             if (root.left != null)                 val = root.left.height + 1;              if (root.right != null)                 val = Math.max(val, root.right.height + 1);              // Update the height of the             // current node             root.height = val;         }     }      // Function to handle Left Left Case     static AVLwithparent LLR(AVLwithparent root) {         // Create a reference to the         // left child         AVLwithparent tmpnode = root.left;          // Update the left child of the         // root to the right child of the         // current left child of the root         root.left = tmpnode.right;          // Update parent pointer of left         // child of the root node         if (tmpnode.right != null)             tmpnode.right.par = root;          // Update the right child of         // tmpnode to root         tmpnode.right = root;          // Update parent pointer of tmpnode         tmpnode.par = root.par;          // Update the parent pointer of root         if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          // Make tmpnode as the new root         root = tmpnode;          // Update the heights         updateHeight(root.left);         updateHeight(root.right);         updateHeight(root);         updateHeight(root.par);          // Return the root node         return root;     }      // Function to handle Right Right Case     static AVLwithparent RRR(AVLwithparent root) {         // Create a reference to the         // right child         AVLwithparent tmpnode = root.right;          // Update the right child of the         // root as the left child of the         // current right child of the root         root.right = tmpnode.left;          // Update parent pointer of the         // right child of the root node         if (tmpnode.left != null)             tmpnode.left.par = root;          // Update the left child of the         // tmpnode to root         tmpnode.left = root;          // Update parent pointer of tmpnode         tmpnode.par = root.par;          // Update the parent pointer of root         if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          // Make tmpnode as the new root         root = tmpnode;          // Update the heights         updateHeight(root.left);         updateHeight(root.right);         updateHeight(root);         updateHeight(root.par);          // Return the root node         return root;     }      // Function to handle Left Right Case     static AVLwithparent LRR(AVLwithparent root) {         root.left = RRR(root.left);         return LLR(root);     }      // Function to handle right left case     static AVLwithparent RLR(AVLwithparent root) {         root.right = LLR(root.right);         return RRR(root);     }      // Function to balance the tree after     // deletion of a node     static AVLwithparent balance(AVLwithparent root) {         // Store the current height of         // the left and right subtree         int firstheight = 0;         int secondheight = 0;          if (root.left != null)             firstheight = root.left.height;          if (root.right != null)             secondheight = root.right.height;          // If current node is not balanced         if (Math.abs(firstheight - secondheight) == 2) {             if (firstheight < secondheight) {                 // Store the height of the                 // left and right subtree                 // of the current node's                 // right subtree                 int rightheight1 = 0;                 int rightheight2 = 0;                 if (root.right.right != null)                     rightheight2 = root.right.right.height;                  if (root.right.left != null)                     rightheight1 = root.right.left.height;                  if (rightheight1 > rightheight2) {                     // Right Left Case                     root = RLR(root);                 } else {                     // Right Right Case                     root = RRR(root);                 }             } else {                 // Store the height of the                 // left and right subtree                 // of the current node's                 // left subtree                 int leftheight1 = 0;                 int leftheight2 = 0;                 if (root.left.right != null)                     leftheight2 = root.left.right.height;                  if (root.left.left != null)                     leftheight1 = root.left.left.height;                  if (leftheight1 > leftheight2) {                     // Left Left Case                     root = LLR(root);                 } else {                     // Left Right Case                     root = LRR(root);                 }             }         }          // Return the root node         return root;     }      // Function to insert a node in     // the AVL tree     static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {         if (root == null) {             // Create and assign values             // to a new node             root = new AVLwithparent(key);             if (root == null)                 System.out.println("Error in memory");             else {                 root.height = 1;                 root.left = null;                 root.right = null;                 root.par = parent;             }         } else if (root.key > key) {             // Recur to the left subtree             // to insert the node             root.left = insert(root.left, root, key);              // Store the heights of the             // left and right subtree             int firstheight = 0;             int secondheight = 0;              if (root.left != null)                 firstheight = root.left.height;              if (root.right != null)                 secondheight = root.right.height;              // Balance the tree if the             // current node is not balanced             if (Math.abs(firstheight - secondheight) == 2) {                 if (root.left != null && key < root.left.key) {                     // Left Left Case                     root = LLR(root);                 } else {                     // Left Right Case                     root = LRR(root);                 }             }         } else if (root.key < key) {             // Recur to the right subtree             // to insert the node             root.right = insert(root.right, root, key);              // Store the heights of the left             // and right subtree             int firstheight = 0;             int secondheight = 0;              if (root.left != null)                 firstheight = root.left.height;              if (root.right != null)                 secondheight = root.right.height;              // Balance the tree if the             // current node is not balanced             if (Math.abs(firstheight - secondheight) == 2) {                 if (root.right != null && key < root.right.key) {                     // Right Left Case                     root = RLR(root);                 } else {                     // Right Right Case                     root = RRR(root);                 }             }         }          // Case when given key is         // already in tree         // Do nothing          // Update the height of the         // root node         updateHeight(root);          // Return the root node         return root;     }      // Function to delete a node from     // the AVL tree     static AVLwithparent delete(AVLwithparent root, int key) {         if (root != null) {             // If the node is found             if (root.key == key) {                 // Replace root with its                 // left child                 if (root.right == null && root.left != null) {                     if (root.par != null) {                         if (root.par.key < root.key)                             root.par.right = root.left;                         else                             root.par.left = root.left;                          // Update the height                         // of root's parent                         updateHeight(root.par);                     }                      root.left.par = root.par;                      // Balance the node                     // after deletion                     root.left = balance(root.left);                     return root.left;                 }                 // Replace root with its                 // right child                 else if (root.left == null && root.right != null) {                     if (root.par != null) {                         if (root.par.key < root.key)                             root.par.right = root.right;                         else                             root.par.left = root.right;                          // Update the height                         // of the root's parent                         updateHeight(root.par);                     }                      root.right.par = root.par;                      // Balance the node after                     // deletion                     root.right = balance(root.right);                     return root.right;                 }                 // Remove the references of                 // the current node                 else if (root.left == null && root.right == null) {                     if (root.par.key < root.key) {                         root.par.right = null;                     } else {                         root.par.left = null;                     }                      if (root.par != null)                         updateHeight(root.par);                      root = null;                     return null;                 }                 // Otherwise, replace the                 // current node with its                 // successor and then                 // recursively call delete()                 else {                     AVLwithparent tmpnode = root;                     tmpnode = tmpnode.right;                     while (tmpnode.left != null) {                         tmpnode = tmpnode.left;                     }                      int val = tmpnode.key;                      root.right = delete(root.right, tmpnode.key);                      root.key = val;                      // Balance the node                     // after deletion                     root = balance(root);                 }             }              // Recur to the right subtree to             // delete the current node             else if (root.key < key) {                 root.right = delete(root.right, key);                  root = balance(root);             }              // Recur into the right subtree             // to delete the current node             else if (root.key > key) {                 root.left = delete(root.left, key);                  root = balance(root);             }              // Update height of the root             if (root != null) {                 updateHeight(root);             }         }          // Handle the case when the key to be         // deleted could not be found         else {             System.out.println("Key to be deleted could not be found");         }          // Return the root node         return root;     }      // Driver Code     public static void main(String[] args) {         AVLwithparent root = null;          // Function call to insert the nodes         root = insert(root, null, 9);         root = insert(root, null, 5);         root = insert(root, null, 10);         root = insert(root, null, 0);         root = insert(root, null, 6);          // Print the tree before deleting node         System.out.println("Before deletion:");         printPreorder(root);          // Function Call to delete node 10         root = delete(root, 10);          // Print the tree after deleting node         System.out.println("After deletion:");         printPreorder(root);     } } 
Python
class AVLwithparent:     def __init__(self, key, parent=None):         self.left = None         self.right = None         self.key = key         self.par = parent         self.height = 1   def print_preorder(root):     if root:         print("Node:", root.key, ", Parent Node:", root.par.key if root.par else "NULL")         print_preorder(root.left)         print_preorder(root.right)   def update_height(root):     if root:         val = 1         if root.left:             val = root.left.height + 1         if root.right:             val = max(val, root.right.height + 1)         root.height = val   def llr(root):     tmp_node = root.left     root.left = tmp_node.right     if tmp_node.right:         tmp_node.right.par = root     tmp_node.right = root     tmp_node.par = root.par     root.par = tmp_node     if tmp_node.par and root.key < tmp_node.par.key:         tmp_node.par.left = tmp_node     elif tmp_node.par:         tmp_node.par.right = tmp_node     root = tmp_node     update_height(root.left)     update_height(root.right)     update_height(root)     update_height(root.par)     return root   def rrr(root):     tmp_node = root.right     root.right = tmp_node.left     if tmp_node.left:         tmp_node.left.par = root     tmp_node.left = root     tmp_node.par = root.par     root.par = tmp_node     if tmp_node.par and root.key < tmp_node.par.key:         tmp_node.par.left = tmp_node     elif tmp_node.par:         tmp_node.par.right = tmp_node     root = tmp_node     update_height(root.left)     update_height(root.right)     update_height(root)     update_height(root.par)     return root   def lrr(root):     root.left = rrr(root.left)     return llr(root)   def rlr(root):     root.right = llr(root.right)     return rrr(root)   def balance(root):     first_height = 0     second_height = 0     if root.left:         first_height = root.left.height     if root.right:         second_height = root.right.height     if abs(first_height - second_height) == 2:         if first_height < second_height:             rightheight1 = 0             rightheight2 = 0             if root.right.right:                 rightheight2 = root.right.right.height             if root.right.left:                 rightheight1 = root.right.left.height             if rightheight1 > rightheight2:                 root = rlr(root)             else:                 root = rrr(root)         else:             leftheight1 = 0             leftheight2 = 0             if root.left.right:                 leftheight2 = root.left.right.height             if root.left.left:                 leftheight1 = root.left.left.height             if leftheight1 > leftheight2:                 root = llr(root)             else:                 root = lrr(root)     return root   def insert(root, parent, key):     if root is None:         root = AVLwithparent(key, parent)     elif root.key > key:         root.left = insert(root.left, root, key)         first_height = 0         second_height = 0         if root.left:             first_height = root.left.height         if root.right:             second_height = root.right.height         if abs(first_height - second_height) == 2:             if root.left and key < root.left.key:                 root = llr(root)             else:                 root = lrr(root)     elif root.key < key:         root.right = insert(root.right, root, key)         first_height = 0         second_height = 0         if root.left:             first_height = root.left.height         if root.right:             second_height = root.right.height         if abs(first_height - second_height) == 2:             if root.right and key < root.right.key:                 root = rlr(root)             else:                 root = rrr(root)     update_height(root)     return root   def delete(root, key):     if root:         if root.key == key:             if root.right is None and root.left is not None:                 if root.par:                     if root.par.key < root.key:                         root.par.right = root.left                     else:                         root.par.left = root.left                     update_height(root.par)                 root.left.par = root.par                 root.left = balance(root.left)                 return root.left             elif root.left is None and root.right is not None:                 if root.par:                     if root.par.key < root.key:                         root.par.right = root.right                     else:                         root.par.left = root.right                     update_height(root.par)                 root.right.par = root.par                 root.right = balance(root.right)                 return root.right             elif root.left is None and root.right is None:                 if root.par:                     if root.par.key < root.key:                         root.par.right = None                     else:                         root.par.left = None                     update_height(root.par)                 root = None                 return None             else:                 tmp_node = root                 tmp_node = tmp_node.right                 while tmp_node.left:                     tmp_node = tmp_node.left                 val = tmp_node.key                 root.right = delete(root.right, tmp_node.key)                 root.key = val                 root = balance(root)         elif root.key < key:             root.right = delete(root.right, key)             root = balance(root)         elif root.key > key:             root.left = delete(root.left, key)             root = balance(root)         update_height(root)     return root   # Driver Code if __name__ == "__main__":     root = None      # Function call to insert the nodes     root = insert(root, None, 9)     root = insert(root, None, 5)     root = insert(root, None, 10)     root = insert(root, None, 0)     root = insert(root, None, 6)      # Print the tree before deleting node     print("Before deletion:")     print_preorder(root)      # Function Call to delete node 10     root = delete(root, 10)      # Print the tree after deleting node     print("After deletion:")     print_preorder(root) 
C#
using System;  // AVL tree node public class AVLwithparent {     public AVLwithparent left;     public AVLwithparent right;     public AVLwithparent par;     public int key;     public int height;      public AVLwithparent(int key)     {         this.key = key;         this.height = 1;     } }  public class AVLTreeWithParent {     // Function to print the preorder traversal of the AVL tree     public static void PrintPreorder(AVLwithparent root)     {         if (root != null)         {             // Print the node's value along with its parent value             Console.Write("Node: " + root.key + ", Parent Node: ");             if (root.par != null)                 Console.WriteLine(root.par.key);             else                 Console.WriteLine("NULL");              // Recur to the left subtree             PrintPreorder(root.left);              // Recur to the right subtree             PrintPreorder(root.right);         }     }      // Function to update the height of a node according to its children's node's heights     public static void UpdateHeight(AVLwithparent root)     {         if (root != null)         {             // Store the height of the current node             int val = 1;              // Store the height of the left and right subtree             if (root.left != null)                 val = root.left.height + 1;             if (root.right != null)                 val = Math.Max(val, root.right.height + 1);              // Update the height of the current node             root.height = val;         }     }      // Function to handle Left Left Case     public static AVLwithparent LLR(AVLwithparent root)     {         AVLwithparent tmpnode = root.left;          root.left = tmpnode.right;         if (tmpnode.right != null)             tmpnode.right.par = root;          tmpnode.right = root;         tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else         {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root.par = tmpnode;          root = tmpnode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      // Function to handle Right Right Case     public static AVLwithparent RRR(AVLwithparent root)     {         AVLwithparent tmpnode = root.right;          root.right = tmpnode.left;         if (tmpnode.left != null)             tmpnode.left.par = root;          tmpnode.left = root;         tmpnode.par = root.par;          if (tmpnode.par != null && root.key < tmpnode.par.key)             tmpnode.par.left = tmpnode;         else         {             if (tmpnode.par != null)                 tmpnode.par.right = tmpnode;         }          root.par = tmpnode;          root = tmpnode;          UpdateHeight(root.left);         UpdateHeight(root.right);         UpdateHeight(root);         UpdateHeight(root.par);          return root;     }      // Function to handle Left Right Case     public static AVLwithparent LRR(AVLwithparent root)     {         root.left = RRR(root.left);         return LLR(root);     }      // Function to handle right left case     public static AVLwithparent RLR(AVLwithparent root)     {         root.right = LLR(root.right);         return RRR(root);     }      // Function to balance the tree after deletion of a node     public static AVLwithparent Balance(AVLwithparent root)     {         int firstheight = 0;         int secondheight = 0;          if (root.left != null)             firstheight = root.left.height;          if (root.right != null)             secondheight = root.right.height;          if (Math.Abs(firstheight - secondheight) == 2)         {             if (firstheight < secondheight)             {                 int rightheight1 = 0;                 int rightheight2 = 0;                 if (root.right.right != null)                     rightheight2 = root.right.right.height;                  if (root.right.left != null)                     rightheight1 = root.right.left.height;                  if (rightheight1 > rightheight2)                     root = RLR(root);                 else                     root = RRR(root);             }             else             {                 int leftheight1 = 0;                 int leftheight2 = 0;                 if (root.left.right != null)                     leftheight2 = root.left.right.height;                  if (root.left.left != null)                     leftheight1 = root.left.left.height;                  if (leftheight1 > leftheight2)                     root = LLR(root);                 else                     root = LRR(root);             }         }          return root;     }      // Function to insert a node in the AVL tree     public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)     {         if (root == null)         {             root = new AVLwithparent(key);             root.par = parent;         }         else if (root.key > key)         {             root.left = Insert(root.left, root, key);             if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)             {                 if (root.left != null && key < root.left.key)                     root = LLR(root);                 else                     root = LRR(root);             }         }         else if (root.key < key)         {             root.right = Insert(root.right, root, key);             if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)             {                 if (root.right != null && key < root.right.key)                     root = RLR(root);                 else                     root = RRR(root);             }         }          UpdateHeight(root);         return root;     }      // Function to delete a node from the AVL tree     public static AVLwithparent Delete(AVLwithparent root, int key)     {         if (root != null)         {             if (root.key == key)             {                 if (root.right == null && root.left != null)                 {                     if (root.par != null)                     {                         if (root.par.key < root.key)                             root.par.right = root.left;                         else                             root.par.left = root.left;                          UpdateHeight(root.par);                     }                      root.left.par = root.par;                     root.left = Balance(root.left);                     return root.left;                 }                 else if (root.left == null && root.right != null)                 {                     if (root.par != null)                     {                         if (root.par.key < root.key)                             root.par.right = root.right;                         else                             root.par.left = root.right;                          UpdateHeight(root.par);                     }                      root.right.par = root.par;                     root.right = Balance(root.right);                     return root.right;                 }                 else if (root.left == null && root.right == null)                 {                     if (root.par != null)                     {                         if (root.par.key < root.key)                             root.par.right = null;                         else                             root.par.left = null;                          UpdateHeight(root.par);                     }                      root = null;                     return null;                 }                 else                 {                     AVLwithparent tmpnode = root.right;                     while (tmpnode.left != null)                         tmpnode = tmpnode.left;                      int val = tmpnode.key;                     root.right = Delete(root.right, tmpnode.key);                     root.key = val;                     root = Balance(root);                 }             }             else if (root.key < key)             {                 root.right = Delete(root.right, key);                 root = Balance(root);             }             else if (root.key > key)             {                 root.left = Delete(root.left, key);                 root = Balance(root);             }              UpdateHeight(root);         }         else             Console.WriteLine("Key to be deleted could not be found");          return root;     }      // Driver Code     public static void Main(string[] args)     {         AVLwithparent root = null;          // Function call to insert the nodes         root = Insert(root, null, 9);         root = Insert(root, null, 5);         root = Insert(root, null, 10);         root = Insert(root, null, 0);         root = Insert(root, null, 6);          // Print the tree before deleting node         Console.WriteLine("Before deletion:");         PrintPreorder(root);          // Function Call to delete node 10         root = Delete(root, 10);          // Print the tree after deleting node         Console.WriteLine("After deletion:");         PrintPreorder(root);     } } //This code is contributed by Utkarsh 
JavaScript
// AVL tree node class AVLwithparent {     constructor(key) {         this.left = null;         this.right = null;         this.key = key;         this.par = null;         this.height = 1;     } }  // Function to print the preorder traversal of the AVL tree function printpreorder(root) {     if (root !== null) {         // Print the node's value along with its parent value         console.log(`Node: ${root.key}, Parent Node: ${root.par ? root.par.key : 'NULL'}`);          // Recur to the left subtree         printpreorder(root.left);          // Recur to the right subtree         printpreorder(root.right);     } }  // Function to update the height of a node according to its children's node's heights function Updateheight(root) {     if (root !== null) {         // Store the height of the current node         let val = 1;          // Store the height of the left and right subtree         if (root.left !== null) {             val = root.left.height + 1;         }          if (root.right !== null) {             val = Math.max(val, root.right.height + 1);         }          // Update the height of the current node         root.height = val;     } }  // Function to handle Left Left Case function LLR(root) {     // Create a reference to the left child     const tmpnode = root.left;      // Update the left child of the root to the right child of the current left child of the root     root.left = tmpnode.right;      // Update parent pointer of left child of the root node     if (tmpnode.right !== null) {         tmpnode.right.par = root;     }      // Update the right child of tmpnode to root     tmpnode.right = root;      // Update parent pointer of tmpnode     tmpnode.par = root.par;      // Update the parent pointer of root     root.par = tmpnode;      // Update tmpnode as the left or the right child of its parent pointer according to its key value     if (tmpnode.par !== null && root.key < tmpnode.par.key) {         tmpnode.par.left = tmpnode;     } else {         if (tmpnode.par !== null) {             tmpnode.par.right = tmpnode;         }     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root.left);     Updateheight(root.right);     Updateheight(root);     Updateheight(root.par);      // Return the root node     return root; }  // Function to handle Right Right Case function RRR(root) {     // Create a reference to the right child     const tmpnode = root.right;      // Update the right child of the root as the left child of the current right child of the root     root.right = tmpnode.left;      // Update parent pointer of the right child of the root node     if (tmpnode.left !== null) {         tmpnode.left.par = root;     }      // Update the left child of the tmpnode to root     tmpnode.left = root;      // Update parent pointer of tmpnode     tmpnode.par = root.par;      // Update the parent pointer of root     root.par = tmpnode;      // Update tmpnode as the left or the right child of its parent pointer according to its key value     if (tmpnode.par !== null && root.key < tmpnode.par.key) {         tmpnode.par.left = tmpnode;     } else {         if (tmpnode.par !== null) {             tmpnode.par.right = tmpnode;         }     }      // Make tmpnode as the new root     root = tmpnode;      // Update the heights     Updateheight(root.left);     Updateheight(root.right);     Updateheight(root);     Updateheight(root.par);      // Return the root node     return root; }  // Function to handle Left Right Case function LRR(root) {     root.left = RRR(root.left);     return LLR(root); }  // Function to handle Right Left Case function RLR(root) {     root.right = LLR(root.right);     return RRR(root); }  // Function to Balance the tree after deletion of a node function Balance(root) {     // Store the current height of the left and right subtree     let firstheight = 0;     let secondheight = 0;      if (root.left !== null) {         firstheight = root.left.height;     }      if (root.right !== null) {         secondheight = root.right.height;     }      // If the current node is not Balanced     if (Math.abs(firstheight - secondheight) === 2) {         if (firstheight < secondheight) {             // Store the height of the left and right subtree of the current node's right subtree             let rightheight1 = 0;             let rightheight2 = 0;             if (root.right.right !== null) {                 rightheight2 = root.right.right.height;             }              if (root.right.left !== null) {                 rightheight1 = root.right.left.height;             }              if (rightheight1 > rightheight2) {                 // Right Left Case                 root = RLR(root);             } else {                 // Right Right Case                 root = RRR(root);             }         } else {             // Store the height of the left and right subtree of the current node's left subtree             let leftheight1 = 0;             let leftheight2 = 0;             if (root.left.right !== null) {                 leftheight2 = root.left.right.height;             }              if (root.left.left !== null) {                 leftheight1 = root.left.left.height;             }              if (leftheight1 > leftheight2) {                 // Left Left Case                 root = LLR(root);             } else {                 // Left Right Case                 root = LRR(root);             }         }     }      // Return the root node     return root; }  // Function to Insert a node in the AVL tree function Insert(root, parent, key) {     if (root === null) {         // Create and assign values to a new node         root = new AVLwithparent(key);         if (root === null) {             console.log("Error in memory");         } else {             root.par = parent;         }     } else if (root.key > key) {         // Recur to the left subtree to Insert the node         root.left = Insert(root.left, root, key);          // Store the heights of the left and right subtree         let firstheight = 0;         let secondheight = 0;          if (root.left !== null) {             firstheight = root.left.height;         }          if (root.right !== null) {             secondheight = root.right.height;         }          // Balance the tree if the current node is not Balanced         if (Math.abs(firstheight - secondheight) === 2) {             if (root.left !== null && key < root.left.key) {                 // Left Left Case                 root = LLR(root);             } else {                 // Left Right Case                 root = LRR(root);             }         }     } else if (root.key < key) {         // Recur to the right subtree to Insert the node         root.right = Insert(root.right, root, key);          // Store the heights of the left and right subtree         let firstheight = 0;         let secondheight = 0;          if (root.left !== null) {             firstheight = root.left.height;         }          if (root.right !== null) {             secondheight = root.right.height;         }          // Balance the tree if the current node is not Balanced         if (Math.abs(firstheight - secondheight) === 2) {             if (root.right !== null && key < root.right.key) {                 // Right Left Case                 root = RLR(root);             } else {                 // Right Right Case                 root = RRR(root);             }         }     }     // Case when given key is already in tree     else {         // Do nothing     }      // Update the height of the root node     Updateheight(root);      // Return the root node     return root; }  // Function to delete a node from the AVL tree function Delete(root, key) {     if (root !== null) {         // If the node is found         if (root.key === key) {             // Replace root with its left child             if (root.right === null && root.left !== null) {                 if (root.par !== null) {                     if (root.par.key < root.key) {                         root.par.right = root.left;                     } else {                         root.par.left = root.left;                     }                      // Update the height of root's parent                     Updateheight(root.par);                 }                  root.left.par = root.par;                  // Balance the node after deletion                 root.left = Balance(root.left);                 return root.left;             }             // Replace root with its right child             else if (root.left === null && root.right !== null) {                 if (root.par !== null) {                     if (root.par.key < root.key) {                         root.par.right = root.right;                     } else {                         root.par.left = root.right;                     }                      // Update the height of the root's parent                     Updateheight(root.par);                 }                  root.right.par = root.par;                  // Balance the node after deletion                 root.right = Balance(root.right);                 return root.right;             }             // Delete the references of the current node             else if (root.left === null && root.right === null) {                 if (root.par.key < root.key) {                     root.par.right = null;                 } else {                     root.par.left = null;                 }                  if (root.par !== null) {                     Updateheight(root.par);                 }                  root = null;                 return null;             }             // Otherwise, replace the current node with its successor and then recursively call Delete()             else {                 let tmpnode = root;                 tmpnode = tmpnode.right;                 while (tmpnode.left !== null) {                     tmpnode = tmpnode.left;                 }                  let val = tmpnode.key;                  root.right = Delete(root.right, tmpnode.key);                  root.key = val;                  // Balance the node after deletion                 root = Balance(root);             }         }         // Recur to the right subtree to delete the current node         else if (root.key < key) {             root.right = Delete(root.right, key);              root = Balance(root);         }         // Recur into the right subtree to delete the current node         else if (root.key > key) {             root.left = Delete(root.left, key);              root = Balance(root);         }          // Update height of the root         if (root !== null) {             Updateheight(root);         }     }     // Handle the case when the key to be deleted could not be found     else {         console.log("Key to be deleted could not be found");     }      // Return the root node     return root; }  // Driver Code let root = null;  // Function call to Insert the nodes root = Insert(root, null, 9); root = Insert(root, null, 5); root = Insert(root, null, 10); root = Insert(root, null, 0); root = Insert(root, null, 6);  // Print the tree before deleting node console.log("Before deletion:"); printpreorder(root);  // Function Call to delete node 10 root = Delete(root, 10);  // Print the tree after deleting node console.log("After deletion:"); printpreorder(root);  // This Code is contributed by Yash Agarwal(yashagarwal2852002) 

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)



Next Article
Deletion in an AVL Tree

A

akshatsachan
Improve
Article Tags :
  • Data Structures
  • DSA
  • Tree
  • AVL-Tree
  • Balanced Binary Search Trees
  • Self-Balancing-BST
Practice Tags :
  • AVL-Tree
  • Data Structures
  • Tree

Similar Reads

  • AVL Tree Data Structure
    An AVL tree defined as a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees for any node cannot be more than one. The absolute difference between the heights of the left subtree and the right subtree for any node is known as the balance factor of
    4 min read
  • What is AVL Tree | AVL Tree meaning
    An AVL is a self-balancing Binary Search Tree (BST) where the difference between the heights of left and right subtrees of any node cannot be more than one. KEY POINTSIt is height balanced treeIt is a binary search treeIt is a binary tree in which the height difference between the left subtree and r
    2 min read
  • Insertion in an AVL Tree
    AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. Example of AVL Tree: The above tree is AVL because the differences between the heights of left and right subtrees for every node are less than
    15+ min read
  • Insertion, Searching and Deletion in AVL trees containing a parent node pointer
    AVL tree is a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. The insertion and deletion in AVL trees have been discussed in the previous article. In this article, insert, search, and delete operations are
    15+ min read
  • Deletion in an AVL Tree
    We have discussed AVL insertion in the previous post. In this post, we will follow a similar approach for deletion. Steps to follow for deletion. To make sure that the given tree remains AVL after every deletion, we must augment the standard BST delete operation to perform some re-balancing. Followi
    15+ min read
  • How is an AVL tree different from a B-tree?
    AVL Trees: AVL tree is a self-balancing binary search tree in which each node maintain an extra factor which is called balance factor whose value is either -1, 0 or 1. B-Tree: A B-tree is a self - balancing tree data structure that keeps data sorted and allows searches, insertions, and deletions in
    1 min read
  • Practice questions on Height balanced/AVL Tree
    AVL tree is binary search tree with additional property that difference between height of left sub-tree and right sub-tree of any node can’t be more than 1. Here are some key points about AVL trees: If there are n nodes in AVL tree, minimum height of AVL tree is floor(log 2 n). If there are n nodes
    4 min read
  • AVL with duplicate keys
    Please refer below post before reading about AVL tree handling of duplicates. How to handle duplicates in Binary Search Tree?This is to augment AVL tree node to store count together with regular fields like key, left and right pointers. Insertion of keys 12, 10, 20, 9, 11, 10, 12, 12 in an empty Bin
    15+ min read
  • Count greater nodes in AVL tree
    In this article we will see that how to calculate number of elements which are greater than given value in AVL tree. Examples: Input : x = 5 Root of below AVL tree 9 / \ 1 10 / \ \ 0 5 11 / / \ -1 2 6 Output : 4 Explanation: there are 4 values which are greater than 5 in AVL tree which are 6, 9, 10
    15+ min read
  • Difference between Binary Search Tree and AVL Tree
    Binary Search Tree:A binary Search Tree is a node-based binary tree data structure that has the following properties: The left subtree of a node contains only nodes with keys lesser than the node’s key.The right subtree of a node contains only nodes with keys greater than the node’s key.The left and
    2 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences