To understand the implementation of a AVL tree using classes using C++
Objective
To understand the implementation of a AVL tree using classes using C++
#include <iostream>
using namespace std;
class Node {
public:
int key;
Node* left;
Node* right;
int height;
};
int height(Node* N) {
if (N == NULL)
return 0;
return N->height;
}
Node* newNode(int key) {
Node* node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially added at leaf
return(node);
}
Node* rightRotate(Node* y) {
Node* x = y->left;
Node* T2 = x->right;
x->right = y;
y->left = T2;
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
return x;
}
Node* leftRotate(Node* x) {
Node* y = x->right;
Node* T2 = y->left;
y->left = x;
x->right = T2;
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
return y;
}
int getBalanceFactor(Node* N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
Node* insertNode(Node* node, int key) {
// Perform the normal BST insertion
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insertNode(node->left, key);
else if (key > node->key)
node->right = insertNode(node->right, key);
else // Equal keys are not allowed in BST
return node;
node->height = 1 + max(height(node->left),
height(node->right));
// Get the balance factor
int balance = getBalanceFactor(node);
// If unbalanced, then there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
void printInOrder(Node* node) {
if(node != NULL) {
printInOrder(node->left);
cout << node->key << " ";
printInOrder(node->right);
}
}
int main() {
Node* root = NULL;
root = insertNode(root, 10);
root = insertNode(root, 20);
root = insertNode(root, 30);
root = insertNode(root, 15);
root = insertNode(root, 5);
printInOrder(root);
return 0;
}
Discusison of Algorithm
- Start.
- Create a new node with the value.
- Check if the tree is empty. If it is, the new node is the root.
- If the tree is not empty, compare the new value with the current node value.
- If the new value is less than the current node value, go to the left child. If the left child is null, insert here. If not, repeat step 4.
- If the new value is greater than the current node value, go to the right child. If the right child is null, insert here. If not, repeat step 4.
- After the new node is inserted, update the height of the affected nodes.
- Check the balance factor of the affected nodes. If it is more than 1 or less than -1, rotations are required to balance the tree.
- If the balance factor is more than 1, and the key of the node to be inserted is less than the key of the left child, perform a right rotation (Left-Left Case).
- If the balance factor is less than -1, and the key of the node to be inserted is more than the key of the right child, perform a left rotation (Right-Right Case).
- If the balance factor is more than 1, and the key of the node to be inserted is more than the key of the left child, perform a left rotation on the left child, followed by a right rotation on the current node (Left-Right Case).
- If the balance factor is less than -1, and the key of the node to be inserted is less than the key of the right child, perform a right rotation on the right child, followed by a left rotation on the current node (Right-Left Case).
- Return the new root node.
- End.
Representations
Flow Diagram
+----------------------------------+ | | | Start | | | | +----------------------------------+ | V +----------------------------------+ | | | Node* root = NULL; | | | | +----------------------------------+ | V +----------------------------------+ | | | root = insertNode(root, 10); | | root = insertNode(root, 20); | | root = insertNode(root, 30); | | root = insertNode(root, 15); | | root = insertNode(root, 5); | | | | +----------------------------------+ | V +----------------------------------+ | | | int balance = | | getBalanceFactor(node); | | | | +----------------------------------+ | V +----------------------------------+ | | | if (balance > 1 && | | key < node->left->key) | | return rightRotate(node); | | | | +----------------------------------+ | V +----------------------------------+ | | | if (balance < -1 && | | key> node->right->key) | | return leftRotate(node); | | | | +----------------------------------+ | V +----------------------------------+ | | | if (balance > 1 && | | key > node->left->key) { | | node->left = | | leftRotate(node->left); | | return rightRotate(node);} | | | | +----------------------------------+ | V +----------------------------------+ | | | if (balance < -1 && | | key < node->right->key) { | | node->right = | | rightRotate(node->right); | | return leftRotate(node);} | | | | +----------------------------------+ | V +----------------------------------+ | | | printInOrder(root); | | | | +----------------------------------+ | V +----------------------------------+ | | | Exit | | | | +----------------------------------+
Tabular Dry Run
Action | Node Value | Operation | Output Tree |
---|---|---|---|
Insert | 10 | Tree is empty, insert 10 at root | 10 |
Insert | 20 | 20 > 10, insert to the right of 10. Tree is unbalanced, perform right rotation at 10 | 20 ← 10 |
Insert | 30 | 30 > 20, insert to the right of 20. Tree is unbalanced, perform left rotation at 20 | 30 ← 20 ← 10 |
Insert | 15 | 15 < 30 and 15 > 20, insert to the right of 20. Tree is unbalanced, perform right rotation at 30 | 20 ← 10, 30 ← 15 |
Insert | 5 | 5 < 20 and 5 < 10, insert to the left of 10. Tree is unbalanced, perform right rotation at 20 | 10 ← 5, 20 ← 15 ← 30 |
Output
5 10 15 20 30