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

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

Insert Operation: The insertion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the parent pointers need to be updated with every insertion and rotation accordingly. Follow the steps below to perform insert operation:
- Perform standard BST insert for the node to be placed at its correct position.
- Increase the height of each node encountered by 1 while finding the correct position for the node to be inserted.
- Update the parent and child pointers of the inserted node and its parent respectively.
- Starting from the inserted node till the root node check if the AVL condition is satisfied for each node on this path.
- If w is the node where the AVL condition is not satisfied then we have 4 cases:
- Left Left Case: (If the left subtree of the left child of w has the inserted node)
- Left Right Case: (If the right subtree of the left child of w has the inserted node)
- Right Left Case: (If the left subtree of the right child of w has the inserted node)
- Right Right Case: (If the right subtree of the right child of w has the inserted node)
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of the
// left child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of
// the tmpnode
tmpnode->par = root->par;
// Update the parent pointer
// of the root
root->par = tmpnode;
// Update tmpnode as the left or the
// right child of its parent pointer
// according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the
// right child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of
// the tmpnode
tmpnode->par = root->par;
// Update the parent pointer
// of the root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
// If the root is NULL
if (root == NULL) {
cout << "Error in memory"
<< endl;
}
// Otherwise
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight
= root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is already
// in the tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(
struct AVLwithparent* root)
{
// Print the node's value along
// with its parent value
cout << "Node: " << root->key
<< ", Parent Node: ";
if (root->par != NULL)
cout << root->par->key << endl;
else
cout << "NULL" << endl;
// Recur to the left subtree
if (root->left != NULL) {
printpreorder(root->left);
}
// Recur to the right subtree
if (root->right != NULL) {
printpreorder(root->right);
}
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function Call to insert nodes
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 20);
root = Insert(root, NULL, 30);
root = Insert(root, NULL, 40);
root = Insert(root, NULL, 50);
root = Insert(root, NULL, 25);
// Function call to print the tree
printpreorder(root);
}
Java
class AVLwithparent {
int key;
AVLwithparent left;
AVLwithparent right;
AVLwithparent par;
int height;
public AVLwithparent(int key) {
this.key = key;
this.left = null;
this.right = null;
this.par = null;
this.height = 1;
}
}
public class AVLTreeWithParent {
// Function to update the height of a node based on its children's heights
public static void updateHeight(AVLwithparent root) {
if (root != null) {
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
root.height = Math.max(leftHeight, rightHeight) + 1;
}
}
// Left-Left Rotation (LLR) to balance the AVL tree
public static AVLwithparent LLR(AVLwithparent root) {
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null) {
tmpnode.right.par = root;
}
tmpnode.right = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par != null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Right-Right Rotation (RRR) to balance the AVL tree
public static AVLwithparent RRR(AVLwithparent root) {
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null) {
tmpnode.left.par = root;
}
tmpnode.left = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par != null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Left-Right Rotation (LRR) to balance the AVL tree
public static AVLwithparent LRR(AVLwithparent root) {
root.left = RRR(root.left);
return LLR(root);
}
// Right-Left Rotation (RLR) to balance the AVL tree
public static AVLwithparent RLR(AVLwithparent root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a key into the AVL tree and balance the tree if needed
public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
root = new AVLwithparent(key);
root.par = parent;
} else if (root.key > key) {
root.left = insert(root.left, root, key);
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) == 2) {
if (key < root.left.key) {
root = LLR(root);
} else {
root = LRR(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
int leftHeight = (root.left != null) ? root.left.height : 0;
int rightHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) == 2) {
if (key < root.right.key) {
root = RLR(root);
} else {
root = RRR(root);
}
}
}
updateHeight(root);
return root;
}
// Function to print the nodes of the AVL tree in preorder
public static void printPreorder(AVLwithparent root) {
if (root != null) {
String parentKey = (root.par != null) ? Integer.toString(root.par.key) : "NULL";
System.out.println("Node: " + root.key + ", Parent Node: " + parentKey);
printPreorder(root.left);
printPreorder(root.right);
}
}
public static void main(String[] args) {
AVLwithparent root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
printPreorder(root);
}
}
Python
class AVLwithparent:
def __init__(self, key):
# Initialize a node with key, left and right child, parent, and height.
self.left = None
self.right = None
self.key = key
self.par = None
self.height = 1
# Function to update the height of a node based on its children's heights
def update_height(root):
if root is not None:
left_height = root.left.height if root.left else 0 # Get the height of the left child
right_height = root.right.height if root.right else 0 # Get the height of the right child
root.height = max(left_height, right_height) + 1 # Update the height of the current node
# Left-Left Rotation (LLR) to balance the AVL tree
def LLR(root):
# Perform a left rotation and then a right rotation
# to balance the tree when there's an imbalance in the left subtree
tmpnode = root.left
root.left = tmpnode.right
if tmpnode.right:
tmpnode.right.par = root
tmpnode.right = root
tmpnode.par = root.par
root.par = tmpnode
if tmpnode.par:
if root.key < tmpnode.par.key:
tmpnode.par.left = tmpnode
else:
tmpnode.par.right = tmpnode
update_height(root)
update_height(tmpnode)
return tmpnode
# Right-Right Rotation (RRR) to balance the AVL tree
def RRR(root):
# Perform a right rotation and then a left rotation
# to balance the tree when there's an imbalance in the right subtree
tmpnode = root.right
root.right = tmpnode.left
if tmpnode.left:
tmpnode.left.par = root
tmpnode.left = root
tmpnode.par = root.par
root.par = tmpnode
if tmpnode.par:
if root.key < tmpnode.par.key:
tmpnode.par.left = tmpnode
else:
tmpnode.par.right = tmpnode
update_height(root)
update_height(tmpnode)
return tmpnode
# Left-Right Rotation (LRR) to balance the AVL tree
def LRR(root):
# Perform a right rotation on the left child and then a left rotation on the root
root.left = RRR(root.left)
return LLR(root)
# Right-Left Rotation (RLR) to balance the AVL tree
def RLR(root):
# Perform a left rotation on the right child and then a right rotation on the root
root.right = LLR(root.right)
return RRR(root)
# Function to insert a key into the AVL tree and balance the tree if needed
def insert(root, parent, key):
if root is None:
root = AVLwithparent(key) # Create a new node if the current node is None
root.par = parent # Set the parent of the new node
elif root.key > key:
# Insert the key into the left subtree and balance the tree if needed
root.left = insert(root.left, root, key)
left_height = root.left.height if root.left else 0
right_height = root.right.height if root.right else 0
if abs(left_height - right_height) == 2:
if key < root.left.key:
root = LLR(root)
else:
root = LRR(root)
elif root.key < key:
# Insert the key into the right subtree and balance the tree if needed
root.right = insert(root.right, root, key)
left_height = root.left.height if root.left else 0
right_height = root.right.height if root.right else 0
if abs(left_height - right_height) == 2:
if key < root.right.key:
root = RLR(root)
else:
root = RRR(root)
update_height(root) # Update the height of the current node after insertion
return root # Return the root of the updated subtree
# Function to print the nodes of the AVL tree in preorder
def print_preorder(root):
if root:
parent_key = root.par.key if root.par else "NULL" # Get the key of the parent node or "NULL" if it's None
print(f"Node: {root.key}, Parent Node: {parent_key}") # Print the node and its parent
print_preorder(root.left) # Print the left subtree in preorder
print_preorder(root.right) # Print the right subtree in preorder
# Main function to demonstrate AVL tree operations
if __name__ == "__main__":
root = None # Initialize the root of the AVL tree as None
# Insert keys into the AVL tree
root = insert(root, None, 10)
root = insert(root, None, 20)
root = insert(root, None, 30)
root = insert(root, None, 40)
root = insert(root, None, 50)
root = insert(root, None, 25)
# Print the AVL tree in preorder
print_preorder(root)
C#
using System;
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public int key;
public AVLwithparent par;
public int height;
}
public class Program
{
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
root.height = val;
}
}
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpNode = root.left;
root.left = tmpNode.right;
if (tmpNode.right != null)
tmpNode.right.par = root;
tmpNode.right = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par != null && root.key < tmpNode.par.key)
{
tmpNode.par.left = tmpNode;
}
else
{
if (tmpNode.par != null)
tmpNode.par.right = tmpNode;
}
root = tmpNode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpNode = root.right;
root.right = tmpNode.left;
if (tmpNode.left != null)
tmpNode.left.par = root;
tmpNode.left = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par != null && root.key < tmpNode.par.key)
{
tmpNode.par.left = tmpNode;
}
else
{
if (tmpNode.par != null)
tmpNode.par.right = tmpNode;
}
root = tmpNode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent
{
height = 1,
left = null,
right = null,
par = parent,
key = key
};
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.left != null && key < root.left.key)
{
root = LLR(root);
}
else
{
root = LRR(root);
}
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.right != null && key < root.right.key)
{
root = RLR(root);
}
else
{
root = RRR(root);
}
}
}
else
{
// Case when given key is already in the tree
}
UpdateHeight(root);
return root;
}
public static void PrintPreorder(AVLwithparent root)
{
Console.Write("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
Console.WriteLine(root.par.key);
else
Console.WriteLine("NULL");
if (root.left != null)
{
PrintPreorder(root.left);
}
if (root.right != null)
{
PrintPreorder(root.right);
}
}
public static void Main()
{
AVLwithparent root = null;
root = Insert(root, null, 10);
root = Insert(root, null, 20);
root = Insert(root, null, 30);
root = Insert(root, null, 40);
root = Insert(root, null, 50);
root = Insert(root, null, 25);
PrintPreorder(root);
}
}
JavaScript
class AVLwithparent {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
this.par = null;
this.height = 1;
}
}
// Function to update the height of a node based on its children's heights
function updateHeight(root) {
if (root !== null) {
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
root.height = Math.max(leftHeight, rightHeight) + 1;
}
}
// Left-Left Rotation (LLR) to balance the AVL tree
function LLR(root) {
const tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right !== null) {
tmpnode.right.par = root;
}
tmpnode.right = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par !== null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Right-Right Rotation (RRR) to balance the AVL tree
function RRR(root) {
const tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left !== null) {
tmpnode.left.par = root;
}
tmpnode.left = root;
tmpnode.par = root.par;
root.par = tmpnode;
if (tmpnode.par !== null) {
if (root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
tmpnode.par.right = tmpnode;
}
}
updateHeight(root);
updateHeight(tmpnode);
return tmpnode;
}
// Left-Right Rotation (LRR) to balance the AVL tree
function LRR(root) {
root.left = RRR(root.left);
return LLR(root);
}
// Right-Left Rotation (RLR) to balance the AVL tree
function RLR(root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a key into the AVL tree and balance the tree if needed
function insert(root, parent, key) {
if (root === null) {
root = new AVLwithparent(key);
root.par = parent;
} else if (root.key > key) {
root.left = insert(root.left, root, key);
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) === 2) {
if (key < root.left.key) {
root = LLR(root);
} else {
root = LRR(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
const leftHeight = (root.left !== null) ? root.left.height : 0;
const rightHeight = (root.right !== null) ? root.right.height : 0;
if (Math.abs(leftHeight - rightHeight) === 2) {
if (key < root.right.key) {
root = RLR(root);
} else {
root = RRR(root);
}
}
}
updateHeight(root);
return root;
}
// Function to print the nodes of the AVL tree in preorder
function printPreorder(root) {
if (root !== null) {
const parentKey = (root.par !== null) ? root.par.key : "NULL";
console.log(`Node: ${root.key}, Parent Node: ${parentKey}`);
printPreorder(root.left);
printPreorder(root.right);
}
}
// Example usage
let root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
printPreorder(root);
OutputNode: 30, Parent Node: NULL
Node: 20, Parent Node: 30
Node: 10, Parent Node: 20
Node: 25, Parent Node: 20
Node: 40, Parent Node: 30
Node: 50, Parent Node: 40
Time Complexity: O(log N), where N is the number of nodes of the tree.
Auxiliary Space: O(1)
Search Operation: The search operation in an AVL tree with parent pointers is similar to the search operation in a normal Binary Search Tree. Follow the steps below to perform search operation:
- Start from the root node.
- If the root node is NULL, return false.
- Check if the current node's value is equal to the value of the node to be searched. If yes, return true.
- If the current node's value is less than searched key then recur to the right subtree.
- If the current node's value is greater than searched key then recur to the left subtree.
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and the right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of the left
// child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the right
// child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
if (root == NULL) {
cout << "Error in memory" << endl;
}
// Otherwise
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Stores the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right, root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to find a key in AVL tree
bool AVLsearch(
struct AVLwithparent* root, int key)
{
// If root is NULL
if (root == NULL)
return false;
// If found, return true
else if (root->key == key)
return true;
// Recur to the left subtree if
// the current node's value is
// greater than key
else if (root->key > key) {
bool val = AVLsearch(root->left, key);
return val;
}
// Otherwise, recur to the
// right subtree
else {
bool val = AVLsearch(root->right, key);
return val;
}
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function call to insert the nodes
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 20);
root = Insert(root, NULL, 30);
root = Insert(root, NULL, 40);
root = Insert(root, NULL, 50);
root = Insert(root, NULL, 25);
// Function call to search for a node
bool found = AVLsearch(root, 40);
if (found)
cout << "value found";
else
cout << "value not found";
return 0;
}
Java
class AVLwithparent {
AVLwithparent left, right, par;
int key;
int height;
// Constructor
public AVLwithparent(int key, AVLwithparent parent) {
this.key = key;
this.par = parent;
this.height = 1;
}
}
public class AVLTree {
// Function to update the height of a node according to its children's node's heights
public static void updateHeight(AVLwithparent root) {
if (root != null) {
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.max(val, root.right.height + 1);
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent llr(AVLwithparent root) {
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent rrr(AVLwithparent root) {
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent lrr(AVLwithparent root) {
root.left = rrr(root.left);
return llr(root);
}
// Function to handle right left case
public static AVLwithparent rlr(AVLwithparent root) {
root.right = llr(root.right);
return rrr(root);
}
// Function to insert a node in the AVL tree
public static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
root = new AVLwithparent(key, parent);
} else if (root.key > key) {
root.left = insert(root.left, root, key);
int firstHeight = (root.left != null) ? root.left.height : 0;
int secondHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) == 2) {
if (root.left != null && key < root.left.key)
root = llr(root);
else
root = lrr(root);
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
int firstHeight = (root.left != null) ? root.left.height : 0;
int secondHeight = (root.right != null) ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) == 2) {
if (root.right != null && key < root.right.key)
root = rlr(root);
else
root = rrr(root);
}
}
updateHeight(root);
return root;
}
// Function to find a key in AVL tree
public static boolean avlSearch(AVLwithparent root, int key) {
if (root == null)
return false;
else if (root.key == key)
return true;
else if (root.key > key)
return avlSearch(root.left, key);
else
return avlSearch(root.right, key);
}
// Driver Code
public static void main(String[] args) {
AVLwithparent root = null;
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
boolean found = avlSearch(root, 40);
if (found)
System.out.println("Value found");
else
System.out.println("Value not found");
}
}
Python
# Python program for the above approach
# AVL tree node
class AVLwithparent:
def __init__(self, key, parent=None):
self.left = None
self.right = None
self.key = key
self.par = parent
self.height = 1
# Function to update the height of
# a node according to its children's
# node's heights
def update_height(root):
if root is not None:
# Store the height of the
# current node
val = 1
# Store the height of the left
# and the right subtree
if root.left is not None:
val = root.left.height + 1
if root.right is not None:
val = max(val, root.right.height + 1)
# Update the height of the
# current node
root.height = val
# Function to handle Left Left Case
def llr(root):
# Create a reference to the
# left child
tmp_node = root.left
# Update the left child of the
# root to the right child of the
# current left child of the root
root.left = tmp_node.right
# Update parent pointer of the left
# child of the root node
if tmp_node.right is not None:
tmp_node.right.par = root
# Update the right child of
# tmp_node to root
tmp_node.right = root
# Update parent pointer of tmp_node
tmp_node.par = root.par
# Update the parent pointer of root
root.par = tmp_node
# Update tmp_node as the left or
# the right child of its parent
# pointer according to its key value
if tmp_node.par is not None and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
else:
if tmp_node.par is not None:
tmp_node.par.right = tmp_node
# Make tmp_node as the new root
root = tmp_node
# Update the heights
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
# Return the root node
return root
# Function to handle Right Right Case
def rrr(root):
# Create a reference to the
# right child
tmp_node = root.right
# Update the right child of the
# root as the left child of the
# current right child of the root
root.right = tmp_node.left
# Update parent pointer of the right
# child of the root node
if tmp_node.left is not None:
tmp_node.left.par = root
# Update the left child of the
# tmp_node to root
tmp_node.left = root
# Update parent pointer of tmp_node
tmp_node.par = root.par
# Update the parent pointer of root
root.par = tmp_node
# Update tmp_node as the left or
# the right child of its parent
# pointer according to its key value
if tmp_node.par is not None and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
else:
if tmp_node.par is not None:
tmp_node.par.right = tmp_node
# Make tmp_node as the new root
root = tmp_node
# Update the heights
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
# Return the root node
return root
# Function to handle Left Right Case
def lrr(root):
root.left = rrr(root.left)
return llr(root)
# Function to handle Right Left Case
def rlr(root):
root.right = llr(root.right)
return rrr(root)
# Function to insert a node in
# the AVL tree
def insert(root, parent, key):
if root is None:
# Create and assign values
# to a new node
root = AVLwithparent(key, parent)
else:
if root.key > key:
# Recur to the left subtree
# to insert the node
root.left = insert(root.left, root, key)
# Stores the heights of the
# left and right subtree
first_height = 0
second_height = 0
if root.left is not None:
first_height = root.left.height
if root.right is not None:
second_height = root.right.height
# Balance the tree if the
# current node is not balanced
if abs(first_height - second_height) == 2:
if root.left is not None and key < root.left.key:
# Left Left Case
root = llr(root)
else:
# Left Right Case
root = lrr(root)
elif root.key < key:
# Recur to the right subtree
# to insert the node
root.right = insert(root.right, root, key)
# Store the heights of the left
# and right subtree
first_height = 0
second_height = 0
if root.left is not None:
first_height = root.left.height
if root.right is not None:
second_height = root.right.height
# Balance the tree if the
# current node is not balanced
if abs(first_height - second_height) == 2:
if root.right is not None and key < root.right.key:
# Right Left Case
root = rlr(root)
else:
# Right Right Case
root = rrr(root)
# Update the height of the
# root node
update_height(root)
# Return the root node
return root
# Function to find a key in AVL tree
def avl_search(root, key):
# If root is None
if root is None:
return False
# If found, return True
elif root.key == key:
return True
# Recur to the left subtree if
# the current node's value is
# greater than key
elif root.key > key:
return avl_search(root.left, key)
# Otherwise, recur to the
# right subtree
else:
return avl_search(root.right, key)
# Driver Code
if __name__ == "__main__":
root = None
# Function call to insert the nodes
root = insert(root, None, 10)
root = insert(root, None, 20)
root = insert(root, None, 30)
root = insert(root, None, 40)
root = insert(root, None, 50)
root = insert(root, None, 25)
# Function call to search for a node
found = avl_search(root, 40)
if found:
print("Value found")
else:
print("Value not found")
C#
using System;
// AVL tree node
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public int key;
public AVLwithparent par;
public int height;
}
public class AVLTree
{
// Function to update the height of a node according to its children's node's heights
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
int val = 1;
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
// Function to insert a node in the AVL tree
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent();
root.height = 1;
root.left = null;
root.right = null;
root.par = parent;
root.key = key;
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.left != null && key < root.left.key)
root = LLR(root);
else
root = LRR(root);
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
int firstHeight = 0;
int secondHeight = 0;
if (root.left != null)
firstHeight = root.left.height;
if (root.right != null)
secondHeight = root.right.height;
if (Math.Abs(firstHeight - secondHeight) == 2)
{
if (root.right != null && key < root.right.key)
root = RLR(root);
else
root = RRR(root);
}
}
UpdateHeight(root);
return root;
}
// Function to find a key in AVL tree
public static bool AVLSearch(AVLwithparent root, int key)
{
if (root == null)
return false;
else if (root.key == key)
return true;
else if (root.key > key)
return AVLSearch(root.left, key);
else
return AVLSearch(root.right, key);
}
// Driver Code
public static void Main(string[] args)
{
AVLwithparent root = null;
root = Insert(root, null, 10);
root = Insert(root, null, 20);
root = Insert(root, null, 30);
root = Insert(root, null, 40);
root = Insert(root, null, 50);
root = Insert(root, null, 25);
bool found = AVLSearch(root, 40);
if (found)
Console.WriteLine("Value found");
else
Console.WriteLine("Value not found");
}
}
JavaScript
class AVLwithparent {
constructor(key, parent = null) {
this.left = null;
this.right = null;
this.key = key;
this.par = parent; // 'par' keeps track of the parent node
this.height = 1; // Height of the node initialized to 1
}
}
// Function to update the height of a node
function updateHeight(root) {
if (root !== null) {
let val = 1;
if (root.left !== null) {
val = root.left.height + 1; // Update height considering the left subtree
}
if (root.right !== null) {
val = Math.max(val, root.right.height + 1); // Update height considering the right subtree
}
root.height = val; // Update the height of the current node
}
}
// Left-Left Rotation (LLR)
function llr(root) {
let tmpNode = root.left;
root.left = tmpNode.right;
if (tmpNode.right !== null) {
tmpNode.right.par = root;
}
tmpNode.right = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par !== null && root.key < tmpNode.par.key) {
tmpNode.par.left = tmpNode;
} else {
if (tmpNode.par !== null) {
tmpNode.par.right = tmpNode;
}
}
root = tmpNode;
// Update heights after rotation
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Right-Right Rotation (RRR)
function rrr(root) {
let tmpNode = root.right;
root.right = tmpNode.left;
if (tmpNode.left !== null) {
tmpNode.left.par = root;
}
tmpNode.left = root;
tmpNode.par = root.par;
root.par = tmpNode;
if (tmpNode.par !== null && root.key < tmpNode.par.key) {
tmpNode.par.left = tmpNode;
} else {
if (tmpNode.par !== null) {
tmpNode.par.right = tmpNode;
}
}
root = tmpNode;
// Update heights after rotation
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
return root;
}
// Left-Right Rotation (LRR)
function lrr(root) {
root.left = rrr(root.left);
return llr(root);
}
// Right-Left Rotation (RLR)
function rlr(root) {
root.right = llr(root.right);
return rrr(root);
}
// Function to insert a node into the AVL tree
function insert(root, parent, key) {
if (root === null) {
root = new AVLwithparent(key, parent);
} else {
if (root.key > key) {
root.left = insert(root.left, root, key);
// Perform rotations if necessary after insertion
let firstHeight = root.left ? root.left.height : 0;
let secondHeight = root.right ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) === 2) {
if (root.left !== null && key < root.left.key) {
root = llr(root);
} else {
root = lrr(root);
}
}
} else if (root.key < key) {
root.right = insert(root.right, root, key);
// Perform rotations if necessary after insertion
let firstHeight = root.left ? root.left.height : 0;
let secondHeight = root.right ? root.right.height : 0;
if (Math.abs(firstHeight - secondHeight) === 2) {
if (root.right !== null && key < root.right.key) {
root = rlr(root);
} else {
root = rrr(root);
}
}
}
}
updateHeight(root); // Update the height of the current node
return root;
}
// Function to search for a node in the AVL tree
function avlSearch(root, key) {
if (root === null) {
return false;
} else if (root.key === key) {
return true;
} else if (root.key > key) {
return avlSearch(root.left, key);
} else {
return avlSearch(root.right, key);
}
}
// Driver Code
let root = null;
// Inserting nodes into the AVL tree
root = insert(root, null, 10);
root = insert(root, null, 20);
root = insert(root, null, 30);
root = insert(root, null, 40);
root = insert(root, null, 50);
root = insert(root, null, 25);
// Searching for a value in the AVL tree
let found = avlSearch(root, 40);
if (found) {
console.log("Value found");
} else {
console.log("Value not found");
}
Time Complexity: O(log N), where N is the number of nodes of the tree
Auxiliary Space: O(1)
Delete Operation: The deletion procedure is similar to that of a normal AVL tree without a parent pointer, but in this case, the references to the parent pointers need to be updated with every deletion and rotation accordingly. Follow the steps below to perform the delete operation:
- Perform the delete procedure as in a normal BST.
- From the node that has been deleted, move towards the root.
- At each node on the path, update the height of the node.
- Check for AVL conditions at each node. Let there be 3 nodes: w, x, y where w is the current node, x is the root of the subtree of w which has greater height and y is the root of the subtree of x which has greater height.
- If the node w is unbalanced, there exists one of the following 4 cases:
- Left Left Case (x is left child of w and y is left child of x)
- Left Right Case (x is left child of w and y is right child of x)
- Right Left Case (x is right child of w and y is left child of x)
- Right Right Case (x is right child of w and y is right child of x)
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// AVL tree node
struct AVLwithparent {
struct AVLwithparent* left;
struct AVLwithparent* right;
int key;
struct AVLwithparent* par;
int height;
};
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(struct AVLwithparent* root)
{
// Print the node's value along
// with its parent value
cout << "Node: " << root->key
<< ", Parent Node: ";
if (root->par != NULL)
cout << root->par->key << endl;
else
cout << "NULL" << endl;
// Recur to the left subtree
if (root->left != NULL) {
printpreorder(root->left);
}
// Recur to the right subtree
if (root->right != NULL) {
printpreorder(root->right);
}
}
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
struct AVLwithparent* root)
{
if (root != NULL) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root->left != NULL)
val = root->left->height + 1;
if (root->right != NULL)
val = max(
val, root->right->height + 1);
// Update the height of the
// current node
root->height = val;
}
}
// Function to handle Left Left Case
struct AVLwithparent* LLR(
struct AVLwithparent* root)
{
// Create a reference to the
// left child
struct AVLwithparent* tmpnode = root->left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root->left = tmpnode->right;
// Update parent pointer of left
// child of the root node
if (tmpnode->right != NULL)
tmpnode->right->par = root;
// Update the right child of
// tmpnode to root
tmpnode->right = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Right Right Case
struct AVLwithparent* RRR(
struct AVLwithparent* root)
{
// Create a reference to the
// right child
struct AVLwithparent* tmpnode = root->right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root->right = tmpnode->left;
// Update parent pointer of the
// right child of the root node
if (tmpnode->left != NULL)
tmpnode->left->par = root;
// Update the left child of the
// tmpnode to root
tmpnode->left = root;
// Update parent pointer of tmpnode
tmpnode->par = root->par;
// Update the parent pointer of root
root->par = tmpnode;
// Update tmpnode as the left or
// the right child of its parent
// pointer according to its key value
if (tmpnode->par != NULL
&& root->key < tmpnode->par->key) {
tmpnode->par->left = tmpnode;
}
else {
if (tmpnode->par != NULL)
tmpnode->par->right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root->left);
Updateheight(root->right);
Updateheight(root);
Updateheight(root->par);
// Return the root node
return root;
}
// Function to handle Left Right Case
struct AVLwithparent* LRR(
struct AVLwithparent* root)
{
root->left = RRR(root->left);
return LLR(root);
}
// Function to handle right left case
struct AVLwithparent* RLR(
struct AVLwithparent* root)
{
root->right = LLR(root->right);
return RRR(root);
}
// Function to balance the tree after
// deletion of a node
struct AVLwithparent* Balance(
struct AVLwithparent* root)
{
// Store the current height of
// the left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// If current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (firstheight < secondheight) {
// Store the height of the
// left and right subtree
// of the current node's
// right subtree
int rightheight1 = 0;
int rightheight2 = 0;
if (root->right->right != NULL)
rightheight2 = root->right->right->height;
if (root->right->left != NULL)
rightheight1 = root->right->left->height;
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
else {
// Store the height of the
// left and right subtree
// of the current node's
// left subtree
int leftheight1 = 0;
int leftheight2 = 0;
if (root->left->right != NULL)
leftheight2 = root->left->right->height;
if (root->left->left != NULL)
leftheight1 = root->left->left->height;
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
struct AVLwithparent* root,
struct AVLwithparent* parent,
int key)
{
if (root == NULL) {
// Create and assign values
// to a new node
root = new struct AVLwithparent;
if (root == NULL)
cout << "Error in memory" << endl;
else {
root->height = 1;
root->left = NULL;
root->right = NULL;
root->par = parent;
root->key = key;
}
}
else if (root->key > key) {
// Recur to the left subtree
// to insert the node
root->left = Insert(root->left,
root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight
- secondheight)
== 2) {
if (root->left != NULL
&& key < root->left->key) {
// Left Left Case
root = LLR(root);
}
else {
// Left Right Case
root = LRR(root);
}
}
}
else if (root->key < key) {
// Recur to the right subtree
// to insert the node
root->right = Insert(root->right,
root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root->left != NULL)
firstheight = root->left->height;
if (root->right != NULL)
secondheight = root->right->height;
// Balance the tree if the
// current node is not balanced
if (abs(firstheight - secondheight) == 2) {
if (root->right != NULL
&& key < root->right->key) {
// Right Left Case
root = RLR(root);
}
else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
else {
}
// Update the height of the
// root node
Updateheight(root);
// Return the root node
return root;
}
// Function to delete a node from
// the AVL tree
struct AVLwithparent* Delete(
struct AVLwithparent* root,
int key)
{
if (root != NULL) {
// If the node is found
if (root->key == key) {
// Replace root with its
// left child
if (root->right == NULL
&& root->left != NULL) {
if (root->par != NULL) {
if (root->par->key
< root->key)
root->par->right = root->left;
else
root->par->left = root->left;
// Update the height
// of root's parent
Updateheight(root->par);
}
root->left->par = root->par;
// Balance the node
// after deletion
root->left = Balance(
root->left);
return root->left;
}
// Replace root with its
// right child
else if (root->left == NULL
&& root->right != NULL) {
if (root->par != NULL) {
if (root->par->key
< root->key)
root->par->right = root->right;
else
root->par->left = root->right;
// Update the height
// of the root's parent
Updateheight(root->par);
}
root->right->par = root->par;
// Balance the node after
// deletion
root->right = Balance(root->right);
return root->right;
}
// Remove the references of
// the current node
else if (root->left == NULL
&& root->right == NULL) {
if (root->par->key < root->key) {
root->par->right = NULL;
}
else {
root->par->left = NULL;
}
if (root->par != NULL)
Updateheight(root->par);
root = NULL;
return NULL;
}
// Otherwise, replace the
// current node with its
// successor and then
// recursively call Delete()
else {
struct AVLwithparent* tmpnode = root;
tmpnode = tmpnode->right;
while (tmpnode->left != NULL) {
tmpnode = tmpnode->left;
}
int val = tmpnode->key;
root->right
= Delete(root->right, tmpnode->key);
root->key = val;
// Balance the node
// after deletion
root = Balance(root);
}
}
// Recur to the right subtree to
// delete the current node
else if (root->key < key) {
root->right = Delete(root->right, key);
root = Balance(root);
}
// Recur into the right subtree
// to delete the current node
else if (root->key > key) {
root->left = Delete(root->left, key);
root = Balance(root);
}
// Update height of the root
if (root != NULL) {
Updateheight(root);
}
}
// Handle the case when the key to be
// deleted could not be found
else {
cout << "Key to be deleted "
<< "could not be found\n";
}
// Return the root node
return root;
}
// Driver Code
int main()
{
struct AVLwithparent* root;
root = NULL;
// Function call to insert the nodes
root = Insert(root, NULL, 9);
root = Insert(root, NULL, 5);
root = Insert(root, NULL, 10);
root = Insert(root, NULL, 0);
root = Insert(root, NULL, 6);
// Print the tree before deleting node
cout << "Before deletion:\n";
printpreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
cout << "After deletion:\n";
printpreorder(root);
}
Java
// Java program for the above approach
class AVLwithparent {
AVLwithparent left, right, par;
int key, height;
AVLwithparent(int item) {
key = item;
height = 1;
}
}
public class AVLTreeWithParent {
// Function to print the preorder
// traversal of the AVL tree
static void printPreorder(AVLwithparent root) {
if (root != null) {
// Print the node's value along
// with its parent value
System.out.print("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
System.out.println(root.par.key);
else
System.out.println("NULL");
// Recur to the left subtree
printPreorder(root.left);
// Recur to the right subtree
printPreorder(root.right);
}
}
// Function to update the height of
// a node according to its children's
// node's heights
static void updateHeight(AVLwithparent root) {
if (root != null) {
// Store the height of the
// current node
int val = 1;
// Store the height of the left
// and right subtree
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.max(val, root.right.height + 1);
// Update the height of the
// current node
root.height = val;
}
}
// Function to handle Left Left Case
static AVLwithparent LLR(AVLwithparent root) {
// Create a reference to the
// left child
AVLwithparent tmpnode = root.left;
// Update the left child of the
// root to the right child of the
// current left child of the root
root.left = tmpnode.right;
// Update parent pointer of left
// child of the root node
if (tmpnode.right != null)
tmpnode.right.par = root;
// Update the right child of
// tmpnode to root
tmpnode.right = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
// Return the root node
return root;
}
// Function to handle Right Right Case
static AVLwithparent RRR(AVLwithparent root) {
// Create a reference to the
// right child
AVLwithparent tmpnode = root.right;
// Update the right child of the
// root as the left child of the
// current right child of the root
root.right = tmpnode.left;
// Update parent pointer of the
// right child of the root node
if (tmpnode.left != null)
tmpnode.left.par = root;
// Update the left child of the
// tmpnode to root
tmpnode.left = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else {
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
updateHeight(root.left);
updateHeight(root.right);
updateHeight(root);
updateHeight(root.par);
// Return the root node
return root;
}
// Function to handle Left Right Case
static AVLwithparent LRR(AVLwithparent root) {
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
static AVLwithparent RLR(AVLwithparent root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to balance the tree after
// deletion of a node
static AVLwithparent balance(AVLwithparent root) {
// Store the current height of
// the left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// If current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (firstheight < secondheight) {
// Store the height of the
// left and right subtree
// of the current node's
// right subtree
int rightheight1 = 0;
int rightheight2 = 0;
if (root.right.right != null)
rightheight2 = root.right.right.height;
if (root.right.left != null)
rightheight1 = root.right.left.height;
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
} else {
// Store the height of the
// left and right subtree
// of the current node's
// left subtree
int leftheight1 = 0;
int leftheight2 = 0;
if (root.left.right != null)
leftheight2 = root.left.right.height;
if (root.left.left != null)
leftheight1 = root.left.left.height;
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to insert a node in
// the AVL tree
static AVLwithparent insert(AVLwithparent root, AVLwithparent parent, int key) {
if (root == null) {
// Create and assign values
// to a new node
root = new AVLwithparent(key);
if (root == null)
System.out.println("Error in memory");
else {
root.height = 1;
root.left = null;
root.right = null;
root.par = parent;
}
} else if (root.key > key) {
// Recur to the left subtree
// to insert the node
root.left = insert(root.left, root, key);
// Store the heights of the
// left and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// Balance the tree if the
// current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (root.left != null && key < root.left.key) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
} else if (root.key < key) {
// Recur to the right subtree
// to insert the node
root.right = insert(root.right, root, key);
// Store the heights of the left
// and right subtree
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
// Balance the tree if the
// current node is not balanced
if (Math.abs(firstheight - secondheight) == 2) {
if (root.right != null && key < root.right.key) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is
// already in tree
// Do nothing
// Update the height of the
// root node
updateHeight(root);
// Return the root node
return root;
}
// Function to delete a node from
// the AVL tree
static AVLwithparent delete(AVLwithparent root, int key) {
if (root != null) {
// If the node is found
if (root.key == key) {
// Replace root with its
// left child
if (root.right == null && root.left != null) {
if (root.par != null) {
if (root.par.key < root.key)
root.par.right = root.left;
else
root.par.left = root.left;
// Update the height
// of root's parent
updateHeight(root.par);
}
root.left.par = root.par;
// Balance the node
// after deletion
root.left = balance(root.left);
return root.left;
}
// Replace root with its
// right child
else if (root.left == null && root.right != null) {
if (root.par != null) {
if (root.par.key < root.key)
root.par.right = root.right;
else
root.par.left = root.right;
// Update the height
// of the root's parent
updateHeight(root.par);
}
root.right.par = root.par;
// Balance the node after
// deletion
root.right = balance(root.right);
return root.right;
}
// Remove the references of
// the current node
else if (root.left == null && root.right == null) {
if (root.par.key < root.key) {
root.par.right = null;
} else {
root.par.left = null;
}
if (root.par != null)
updateHeight(root.par);
root = null;
return null;
}
// Otherwise, replace the
// current node with its
// successor and then
// recursively call delete()
else {
AVLwithparent tmpnode = root;
tmpnode = tmpnode.right;
while (tmpnode.left != null) {
tmpnode = tmpnode.left;
}
int val = tmpnode.key;
root.right = delete(root.right, tmpnode.key);
root.key = val;
// Balance the node
// after deletion
root = balance(root);
}
}
// Recur to the right subtree to
// delete the current node
else if (root.key < key) {
root.right = delete(root.right, key);
root = balance(root);
}
// Recur into the right subtree
// to delete the current node
else if (root.key > key) {
root.left = delete(root.left, key);
root = balance(root);
}
// Update height of the root
if (root != null) {
updateHeight(root);
}
}
// Handle the case when the key to be
// deleted could not be found
else {
System.out.println("Key to be deleted could not be found");
}
// Return the root node
return root;
}
// Driver Code
public static void main(String[] args) {
AVLwithparent root = null;
// Function call to insert the nodes
root = insert(root, null, 9);
root = insert(root, null, 5);
root = insert(root, null, 10);
root = insert(root, null, 0);
root = insert(root, null, 6);
// Print the tree before deleting node
System.out.println("Before deletion:");
printPreorder(root);
// Function Call to delete node 10
root = delete(root, 10);
// Print the tree after deleting node
System.out.println("After deletion:");
printPreorder(root);
}
}
Python
class AVLwithparent:
def __init__(self, key, parent=None):
self.left = None
self.right = None
self.key = key
self.par = parent
self.height = 1
def print_preorder(root):
if root:
print("Node:", root.key, ", Parent Node:", root.par.key if root.par else "NULL")
print_preorder(root.left)
print_preorder(root.right)
def update_height(root):
if root:
val = 1
if root.left:
val = root.left.height + 1
if root.right:
val = max(val, root.right.height + 1)
root.height = val
def llr(root):
tmp_node = root.left
root.left = tmp_node.right
if tmp_node.right:
tmp_node.right.par = root
tmp_node.right = root
tmp_node.par = root.par
root.par = tmp_node
if tmp_node.par and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
elif tmp_node.par:
tmp_node.par.right = tmp_node
root = tmp_node
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
return root
def rrr(root):
tmp_node = root.right
root.right = tmp_node.left
if tmp_node.left:
tmp_node.left.par = root
tmp_node.left = root
tmp_node.par = root.par
root.par = tmp_node
if tmp_node.par and root.key < tmp_node.par.key:
tmp_node.par.left = tmp_node
elif tmp_node.par:
tmp_node.par.right = tmp_node
root = tmp_node
update_height(root.left)
update_height(root.right)
update_height(root)
update_height(root.par)
return root
def lrr(root):
root.left = rrr(root.left)
return llr(root)
def rlr(root):
root.right = llr(root.right)
return rrr(root)
def balance(root):
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if first_height < second_height:
rightheight1 = 0
rightheight2 = 0
if root.right.right:
rightheight2 = root.right.right.height
if root.right.left:
rightheight1 = root.right.left.height
if rightheight1 > rightheight2:
root = rlr(root)
else:
root = rrr(root)
else:
leftheight1 = 0
leftheight2 = 0
if root.left.right:
leftheight2 = root.left.right.height
if root.left.left:
leftheight1 = root.left.left.height
if leftheight1 > leftheight2:
root = llr(root)
else:
root = lrr(root)
return root
def insert(root, parent, key):
if root is None:
root = AVLwithparent(key, parent)
elif root.key > key:
root.left = insert(root.left, root, key)
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if root.left and key < root.left.key:
root = llr(root)
else:
root = lrr(root)
elif root.key < key:
root.right = insert(root.right, root, key)
first_height = 0
second_height = 0
if root.left:
first_height = root.left.height
if root.right:
second_height = root.right.height
if abs(first_height - second_height) == 2:
if root.right and key < root.right.key:
root = rlr(root)
else:
root = rrr(root)
update_height(root)
return root
def delete(root, key):
if root:
if root.key == key:
if root.right is None and root.left is not None:
if root.par:
if root.par.key < root.key:
root.par.right = root.left
else:
root.par.left = root.left
update_height(root.par)
root.left.par = root.par
root.left = balance(root.left)
return root.left
elif root.left is None and root.right is not None:
if root.par:
if root.par.key < root.key:
root.par.right = root.right
else:
root.par.left = root.right
update_height(root.par)
root.right.par = root.par
root.right = balance(root.right)
return root.right
elif root.left is None and root.right is None:
if root.par:
if root.par.key < root.key:
root.par.right = None
else:
root.par.left = None
update_height(root.par)
root = None
return None
else:
tmp_node = root
tmp_node = tmp_node.right
while tmp_node.left:
tmp_node = tmp_node.left
val = tmp_node.key
root.right = delete(root.right, tmp_node.key)
root.key = val
root = balance(root)
elif root.key < key:
root.right = delete(root.right, key)
root = balance(root)
elif root.key > key:
root.left = delete(root.left, key)
root = balance(root)
update_height(root)
return root
# Driver Code
if __name__ == "__main__":
root = None
# Function call to insert the nodes
root = insert(root, None, 9)
root = insert(root, None, 5)
root = insert(root, None, 10)
root = insert(root, None, 0)
root = insert(root, None, 6)
# Print the tree before deleting node
print("Before deletion:")
print_preorder(root)
# Function Call to delete node 10
root = delete(root, 10)
# Print the tree after deleting node
print("After deletion:")
print_preorder(root)
C#
using System;
// AVL tree node
public class AVLwithparent
{
public AVLwithparent left;
public AVLwithparent right;
public AVLwithparent par;
public int key;
public int height;
public AVLwithparent(int key)
{
this.key = key;
this.height = 1;
}
}
public class AVLTreeWithParent
{
// Function to print the preorder traversal of the AVL tree
public static void PrintPreorder(AVLwithparent root)
{
if (root != null)
{
// Print the node's value along with its parent value
Console.Write("Node: " + root.key + ", Parent Node: ");
if (root.par != null)
Console.WriteLine(root.par.key);
else
Console.WriteLine("NULL");
// Recur to the left subtree
PrintPreorder(root.left);
// Recur to the right subtree
PrintPreorder(root.right);
}
}
// Function to update the height of a node according to its children's node's heights
public static void UpdateHeight(AVLwithparent root)
{
if (root != null)
{
// Store the height of the current node
int val = 1;
// Store the height of the left and right subtree
if (root.left != null)
val = root.left.height + 1;
if (root.right != null)
val = Math.Max(val, root.right.height + 1);
// Update the height of the current node
root.height = val;
}
}
// Function to handle Left Left Case
public static AVLwithparent LLR(AVLwithparent root)
{
AVLwithparent tmpnode = root.left;
root.left = tmpnode.right;
if (tmpnode.right != null)
tmpnode.right.par = root;
tmpnode.right = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root.par = tmpnode;
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Right Right Case
public static AVLwithparent RRR(AVLwithparent root)
{
AVLwithparent tmpnode = root.right;
root.right = tmpnode.left;
if (tmpnode.left != null)
tmpnode.left.par = root;
tmpnode.left = root;
tmpnode.par = root.par;
if (tmpnode.par != null && root.key < tmpnode.par.key)
tmpnode.par.left = tmpnode;
else
{
if (tmpnode.par != null)
tmpnode.par.right = tmpnode;
}
root.par = tmpnode;
root = tmpnode;
UpdateHeight(root.left);
UpdateHeight(root.right);
UpdateHeight(root);
UpdateHeight(root.par);
return root;
}
// Function to handle Left Right Case
public static AVLwithparent LRR(AVLwithparent root)
{
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle right left case
public static AVLwithparent RLR(AVLwithparent root)
{
root.right = LLR(root.right);
return RRR(root);
}
// Function to balance the tree after deletion of a node
public static AVLwithparent Balance(AVLwithparent root)
{
int firstheight = 0;
int secondheight = 0;
if (root.left != null)
firstheight = root.left.height;
if (root.right != null)
secondheight = root.right.height;
if (Math.Abs(firstheight - secondheight) == 2)
{
if (firstheight < secondheight)
{
int rightheight1 = 0;
int rightheight2 = 0;
if (root.right.right != null)
rightheight2 = root.right.right.height;
if (root.right.left != null)
rightheight1 = root.right.left.height;
if (rightheight1 > rightheight2)
root = RLR(root);
else
root = RRR(root);
}
else
{
int leftheight1 = 0;
int leftheight2 = 0;
if (root.left.right != null)
leftheight2 = root.left.right.height;
if (root.left.left != null)
leftheight1 = root.left.left.height;
if (leftheight1 > leftheight2)
root = LLR(root);
else
root = LRR(root);
}
}
return root;
}
// Function to insert a node in the AVL tree
public static AVLwithparent Insert(AVLwithparent root, AVLwithparent parent, int key)
{
if (root == null)
{
root = new AVLwithparent(key);
root.par = parent;
}
else if (root.key > key)
{
root.left = Insert(root.left, root, key);
if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)
{
if (root.left != null && key < root.left.key)
root = LLR(root);
else
root = LRR(root);
}
}
else if (root.key < key)
{
root.right = Insert(root.right, root, key);
if (Math.Abs((root.left != null ? root.left.height : 0) - (root.right != null ? root.right.height : 0)) == 2)
{
if (root.right != null && key < root.right.key)
root = RLR(root);
else
root = RRR(root);
}
}
UpdateHeight(root);
return root;
}
// Function to delete a node from the AVL tree
public static AVLwithparent Delete(AVLwithparent root, int key)
{
if (root != null)
{
if (root.key == key)
{
if (root.right == null && root.left != null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = root.left;
else
root.par.left = root.left;
UpdateHeight(root.par);
}
root.left.par = root.par;
root.left = Balance(root.left);
return root.left;
}
else if (root.left == null && root.right != null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = root.right;
else
root.par.left = root.right;
UpdateHeight(root.par);
}
root.right.par = root.par;
root.right = Balance(root.right);
return root.right;
}
else if (root.left == null && root.right == null)
{
if (root.par != null)
{
if (root.par.key < root.key)
root.par.right = null;
else
root.par.left = null;
UpdateHeight(root.par);
}
root = null;
return null;
}
else
{
AVLwithparent tmpnode = root.right;
while (tmpnode.left != null)
tmpnode = tmpnode.left;
int val = tmpnode.key;
root.right = Delete(root.right, tmpnode.key);
root.key = val;
root = Balance(root);
}
}
else if (root.key < key)
{
root.right = Delete(root.right, key);
root = Balance(root);
}
else if (root.key > key)
{
root.left = Delete(root.left, key);
root = Balance(root);
}
UpdateHeight(root);
}
else
Console.WriteLine("Key to be deleted could not be found");
return root;
}
// Driver Code
public static void Main(string[] args)
{
AVLwithparent root = null;
// Function call to insert the nodes
root = Insert(root, null, 9);
root = Insert(root, null, 5);
root = Insert(root, null, 10);
root = Insert(root, null, 0);
root = Insert(root, null, 6);
// Print the tree before deleting node
Console.WriteLine("Before deletion:");
PrintPreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
Console.WriteLine("After deletion:");
PrintPreorder(root);
}
}
//This code is contributed by Utkarsh
JavaScript
// AVL tree node
class AVLwithparent {
constructor(key) {
this.left = null;
this.right = null;
this.key = key;
this.par = null;
this.height = 1;
}
}
// Function to print the preorder traversal of the AVL tree
function printpreorder(root) {
if (root !== null) {
// Print the node's value along with its parent value
console.log(`Node: ${root.key}, Parent Node: ${root.par ? root.par.key : 'NULL'}`);
// Recur to the left subtree
printpreorder(root.left);
// Recur to the right subtree
printpreorder(root.right);
}
}
// Function to update the height of a node according to its children's node's heights
function Updateheight(root) {
if (root !== null) {
// Store the height of the current node
let val = 1;
// Store the height of the left and right subtree
if (root.left !== null) {
val = root.left.height + 1;
}
if (root.right !== null) {
val = Math.max(val, root.right.height + 1);
}
// Update the height of the current node
root.height = val;
}
}
// Function to handle Left Left Case
function LLR(root) {
// Create a reference to the left child
const tmpnode = root.left;
// Update the left child of the root to the right child of the current left child of the root
root.left = tmpnode.right;
// Update parent pointer of left child of the root node
if (tmpnode.right !== null) {
tmpnode.right.par = root;
}
// Update the right child of tmpnode to root
tmpnode.right = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
root.par = tmpnode;
// Update tmpnode as the left or the right child of its parent pointer according to its key value
if (tmpnode.par !== null && root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
if (tmpnode.par !== null) {
tmpnode.par.right = tmpnode;
}
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root.left);
Updateheight(root.right);
Updateheight(root);
Updateheight(root.par);
// Return the root node
return root;
}
// Function to handle Right Right Case
function RRR(root) {
// Create a reference to the right child
const tmpnode = root.right;
// Update the right child of the root as the left child of the current right child of the root
root.right = tmpnode.left;
// Update parent pointer of the right child of the root node
if (tmpnode.left !== null) {
tmpnode.left.par = root;
}
// Update the left child of the tmpnode to root
tmpnode.left = root;
// Update parent pointer of tmpnode
tmpnode.par = root.par;
// Update the parent pointer of root
root.par = tmpnode;
// Update tmpnode as the left or the right child of its parent pointer according to its key value
if (tmpnode.par !== null && root.key < tmpnode.par.key) {
tmpnode.par.left = tmpnode;
} else {
if (tmpnode.par !== null) {
tmpnode.par.right = tmpnode;
}
}
// Make tmpnode as the new root
root = tmpnode;
// Update the heights
Updateheight(root.left);
Updateheight(root.right);
Updateheight(root);
Updateheight(root.par);
// Return the root node
return root;
}
// Function to handle Left Right Case
function LRR(root) {
root.left = RRR(root.left);
return LLR(root);
}
// Function to handle Right Left Case
function RLR(root) {
root.right = LLR(root.right);
return RRR(root);
}
// Function to Balance the tree after deletion of a node
function Balance(root) {
// Store the current height of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// If the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (firstheight < secondheight) {
// Store the height of the left and right subtree of the current node's right subtree
let rightheight1 = 0;
let rightheight2 = 0;
if (root.right.right !== null) {
rightheight2 = root.right.right.height;
}
if (root.right.left !== null) {
rightheight1 = root.right.left.height;
}
if (rightheight1 > rightheight2) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
} else {
// Store the height of the left and right subtree of the current node's left subtree
let leftheight1 = 0;
let leftheight2 = 0;
if (root.left.right !== null) {
leftheight2 = root.left.right.height;
}
if (root.left.left !== null) {
leftheight1 = root.left.left.height;
}
if (leftheight1 > leftheight2) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
}
// Return the root node
return root;
}
// Function to Insert a node in the AVL tree
function Insert(root, parent, key) {
if (root === null) {
// Create and assign values to a new node
root = new AVLwithparent(key);
if (root === null) {
console.log("Error in memory");
} else {
root.par = parent;
}
} else if (root.key > key) {
// Recur to the left subtree to Insert the node
root.left = Insert(root.left, root, key);
// Store the heights of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// Balance the tree if the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (root.left !== null && key < root.left.key) {
// Left Left Case
root = LLR(root);
} else {
// Left Right Case
root = LRR(root);
}
}
} else if (root.key < key) {
// Recur to the right subtree to Insert the node
root.right = Insert(root.right, root, key);
// Store the heights of the left and right subtree
let firstheight = 0;
let secondheight = 0;
if (root.left !== null) {
firstheight = root.left.height;
}
if (root.right !== null) {
secondheight = root.right.height;
}
// Balance the tree if the current node is not Balanced
if (Math.abs(firstheight - secondheight) === 2) {
if (root.right !== null && key < root.right.key) {
// Right Left Case
root = RLR(root);
} else {
// Right Right Case
root = RRR(root);
}
}
}
// Case when given key is already in tree
else {
// Do nothing
}
// Update the height of the root node
Updateheight(root);
// Return the root node
return root;
}
// Function to delete a node from the AVL tree
function Delete(root, key) {
if (root !== null) {
// If the node is found
if (root.key === key) {
// Replace root with its left child
if (root.right === null && root.left !== null) {
if (root.par !== null) {
if (root.par.key < root.key) {
root.par.right = root.left;
} else {
root.par.left = root.left;
}
// Update the height of root's parent
Updateheight(root.par);
}
root.left.par = root.par;
// Balance the node after deletion
root.left = Balance(root.left);
return root.left;
}
// Replace root with its right child
else if (root.left === null && root.right !== null) {
if (root.par !== null) {
if (root.par.key < root.key) {
root.par.right = root.right;
} else {
root.par.left = root.right;
}
// Update the height of the root's parent
Updateheight(root.par);
}
root.right.par = root.par;
// Balance the node after deletion
root.right = Balance(root.right);
return root.right;
}
// Delete the references of the current node
else if (root.left === null && root.right === null) {
if (root.par.key < root.key) {
root.par.right = null;
} else {
root.par.left = null;
}
if (root.par !== null) {
Updateheight(root.par);
}
root = null;
return null;
}
// Otherwise, replace the current node with its successor and then recursively call Delete()
else {
let tmpnode = root;
tmpnode = tmpnode.right;
while (tmpnode.left !== null) {
tmpnode = tmpnode.left;
}
let val = tmpnode.key;
root.right = Delete(root.right, tmpnode.key);
root.key = val;
// Balance the node after deletion
root = Balance(root);
}
}
// Recur to the right subtree to delete the current node
else if (root.key < key) {
root.right = Delete(root.right, key);
root = Balance(root);
}
// Recur into the right subtree to delete the current node
else if (root.key > key) {
root.left = Delete(root.left, key);
root = Balance(root);
}
// Update height of the root
if (root !== null) {
Updateheight(root);
}
}
// Handle the case when the key to be deleted could not be found
else {
console.log("Key to be deleted could not be found");
}
// Return the root node
return root;
}
// Driver Code
let root = null;
// Function call to Insert the nodes
root = Insert(root, null, 9);
root = Insert(root, null, 5);
root = Insert(root, null, 10);
root = Insert(root, null, 0);
root = Insert(root, null, 6);
// Print the tree before deleting node
console.log("Before deletion:");
printpreorder(root);
// Function Call to delete node 10
root = Delete(root, 10);
// Print the tree after deleting node
console.log("After deletion:");
printpreorder(root);
// This Code is contributed by Yash Agarwal(yashagarwal2852002)
OutputBefore deletion:
Node: 9, Parent Node: NULL
Node: 5, Parent Node: 9
Node: 0, Parent Node: 5
Node: 6, Parent Node: 5
Node: 10, Parent Node: 9
After deletion:
Node: 6, Parent Node: NULL
Node: 5, Parent ...
Time Complexity: O(log N), where N is the number of nodes of the tree
Auxiliary Space: O(1)
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem