Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Inserting a node in a Javascript AVL Tree
We can learn how to insert a node in an AVL Tree. Insertions in AVL trees follow the same process as BST, but we need to perform one extra step called balance tree during insert whenever we move down the tree.
This requires calculating the balance factor and applying appropriate rotation methods based on the tree configuration. The balance factor determines which type of rotation is needed to maintain the AVL property.
Understanding AVL Tree Balance
An AVL tree maintains balance by ensuring that for every node, the heights of its left and right subtrees differ by at most 1. When this property is violated during insertion, we perform rotations to restore balance.
Implementation
We create a class method and a helper function for recursive calls:
insert(data) {
let node = new this.Node(data);
// Check if the tree is empty
if (this.root === null) {
// Insert as the first element
this.root = node;
} else {
this.root = this.insertHelper(this.root, node);
}
}
Helper Method
insertHelper(root, node) {
if (root === null) {
return node;
}
if (node.data < root.data) {
// Go left!
root.left = this.insertHelper(root.left, node);
// Check for balance factor and perform appropriate rotation
if (this.getBalanceFactor(root) > 1) {
if (node.data < root.left.data) {
root = this.rotationLL(root);
} else {
root = this.rotationLR(root);
}
}
} else if (node.data > root.data) {
// Go right!
root.right = this.insertHelper(root.right, node);
// Check for balance factor and perform appropriate rotation
if (this.getBalanceFactor(root) < -1) {
if (node.data > root.right.data) {
root = this.rotationRR(root);
} else {
root = this.rotationRL(root);
}
}
}
return root;
}
Complete Example
Here's how to test the AVL tree insertion:
class Node {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
this.height = 1;
}
}
class AVLTree {
constructor() {
this.root = null;
}
getHeight(node) {
return node ? node.height : 0;
}
getBalanceFactor(node) {
return node ? this.getHeight(node.left) - this.getHeight(node.right) : 0;
}
updateHeight(node) {
node.height = Math.max(this.getHeight(node.left), this.getHeight(node.right)) + 1;
}
rotationLL(node) {
let newRoot = node.left;
node.left = newRoot.right;
newRoot.right = node;
this.updateHeight(node);
this.updateHeight(newRoot);
return newRoot;
}
rotationRR(node) {
let newRoot = node.right;
node.right = newRoot.left;
newRoot.left = node;
this.updateHeight(node);
this.updateHeight(newRoot);
return newRoot;
}
rotationLR(node) {
node.left = this.rotationRR(node.left);
return this.rotationLL(node);
}
rotationRL(node) {
node.right = this.rotationLL(node.right);
return this.rotationRR(node);
}
insert(data) {
this.root = this.insertHelper(this.root, data);
}
insertHelper(root, data) {
if (!root) {
return new Node(data);
}
if (data < root.data) {
root.left = this.insertHelper(root.left, data);
} else if (data > root.data) {
root.right = this.insertHelper(root.right, data);
} else {
return root; // Duplicate values not allowed
}
this.updateHeight(root);
let balance = this.getBalanceFactor(root);
// Left-Left case
if (balance > 1 && data < root.left.data) {
return this.rotationLL(root);
}
// Right-Right case
if (balance < -1 && data > root.right.data) {
return this.rotationRR(root);
}
// Left-Right case
if (balance > 1 && data > root.left.data) {
return this.rotationLR(root);
}
// Right-Left case
if (balance < -1 && data < root.right.data) {
return this.rotationRL(root);
}
return root;
}
inOrder(node = this.root) {
if (node) {
this.inOrder(node.left);
console.log(node.data);
this.inOrder(node.right);
}
}
}
// Test the AVL tree
let avl = new AVLTree();
avl.insert(10);
avl.insert(15);
avl.insert(5);
avl.insert(50);
avl.insert(3);
avl.insert(7);
avl.insert(12);
console.log("In-order traversal of AVL tree:");
avl.inOrder();
In-order traversal of AVL tree: 3 5 7 10 12 15 50
Key Points
- Balance Factor: Height of left subtree minus height of right subtree
- AVL Property: Balance factor must be -1, 0, or 1 for all nodes
- Rotations: LL, RR, LR, and RL rotations restore balance when violated
- Height Update: Node heights must be updated after each insertion and rotation
Conclusion
AVL tree insertion maintains balance through rotations based on balance factors. This ensures O(log n) search, insert, and delete operations by keeping the tree height minimal.
