AVL Tree
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
int height;
struct Node * left;
struct Node * right;
} Node;
typedef struct AVLTree {
Node * root;
} AVLTree;
Node * initNode (int data);
void insert(AVLTree * tree, int data);
Node * insertRecursive(Node * current, int data);
int getHeight(Node * node);
void updateHeight(Node * node);
Node * rotateLeft(Node * node) ;
Node * rotateRight(Node * node);
void deleteNode(AVLTree * tree, int data);
Node * deleteRecursive(Node * current, int data);
Node * getMin(Node * node);
void printInorder(AVLTree * tree);
void printInorderRecursive(Node * current);
void freeTree(Node * root);
Node * initNode (int data) {
Node * newNode = malloc(sizeof(Node));
newNode->data = data;
newNode->height = 0;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void insert(AVLTree * tree, int data) {
if (!tree) return;
tree->root = insertRecursive(tree->root, data);
}
Node * insertRecursive(Node * current, int data) {
if (!current) // Reached endpoint where data must be inserted
return initNode(data);
if (data == current->data)
return current; // If data already exists, return without adding to tree
// Recursively traverses to left or right through tree to find where data belongs
if (data < current->data) {
current->left = insertRecursive(current->left, data);
}
else {
current->right = insertRecursive(current->right, data);
}
// Recursively backtracking through tree after insertion beyond this line
// Update current node's height
updateHeight(current);
// Get balance factor
int balanceFactor = getHeight(current->left) - getHeight(current->right);
// If |balance factor| > 1 , determine type of rotation required and call rotate
// Left Left case
if (balanceFactor > 1 && data < current->left->data) {
return rotateRight(current);
}
// Right Right case
if (balanceFactor < -1 && data > current->right->data) {
return rotateLeft(current);
}
// Left Right case
if (balanceFactor > 1 && data > current->left->data) {
current->left = rotateLeft(current->left);
return rotateRight(current);
}
// Right Left case
if (balanceFactor < -1 && data < current->right->data) {
current->right = rotateRight(current->right);
return rotateLeft(current);
}
return current;
}
// Return a given node's height. Returns -1 if node is NULL
int getHeight(Node * node) {
if (!node) return -1;
return node->height;
}
// Update node's height to be larger of the two subtree heights + 1
void updateHeight(Node * node) {
if (!node) return;
int leftSubtreeHeight = getHeight(node->left);
int rightSubtreeHeight = getHeight(node->right);
int maxSubtreeHeight = leftSubtreeHeight > rightSubtreeHeight ?
leftSubtreeHeight : rightSubtreeHeight;
node->height = maxSubtreeHeight + 1;
}
// Right child becomes new root
// Original node becomes left child of new root
// New root's left subtree is transferred to original node's right
Node * rotateLeft(Node * node) {
Node * newRoot = node->right;
Node * movedSubtree = newRoot->left;
newRoot->left = node;
node->right = movedSubtree;
// Update node heights starting with lower of the two modified nodes
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
// Left child becomes new root
// Original node becomes right child of new root
// New root's right subtree is transferred to original node's left
Node * rotateRight(Node * node) {
Node * newRoot = node->left;
Node * movedSubtree = newRoot->right;
newRoot->right = node;
node->left = movedSubtree;
// Update node heights starting with lower of the two modified nodes
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
void deleteNode(AVLTree * tree, int data) {
if (!tree) return;
tree->root = deleteRecursive(tree->root, data);
}
Node * deleteRecursive(Node * current, int data) {
if (!current) return NULL;
// Recursively call delete node in the direction of data
if (data < current->data) {
current->left = deleteRecursive(current->left, data);
}
else if (data > current->data) {
current->right = deleteRecursive(current->right, data);
}
else // data == current->data , so current node is node to be deleted
{
// 0 or 1 child
// Saves a reference to child or NULL. Deletes current node.
// Returns child or NULL
if (!current->left || !current->right) {
Node * temp = current->left ? current->left : current->right;
free(current);
return temp;
}
else // 2 children
{
// Get the leftmost node from the right subtree (successor)
// Copy data from successor into current node.
// Delete successor
Node * successor = getMin(current->right);
current->data = successor->data;
current->right = deleteRecursive(current->right, successor->data);
}
}
// Update height
updateHeight(current);
// Just like during insertion, must rebalance during recursive backtracking
// Unlike insertion, AVL deletion determines rotation cases
// using subtree heights, NOT the deleted value.
// Get balance factor
int balanceFactor = getHeight(current->left) - getHeight(current->right);
// If |balance factor| > 1 , determine type of rotation required and call rotate
// Left heavy subtree
// Fix with right rotation
if (balanceFactor > 1) {
if (getHeight(current->left->left) >= getHeight(current->left->right)) {
return rotateRight(current); // Left Left
} else {
current->left = rotateLeft(current->left); // Left Right
return rotateRight(current);
}
}
// Right heavy subtree
// Fix with left rotation
if (balanceFactor < -1) {
if (getHeight(current->right->right) >= getHeight(current->right->left)) {
return rotateLeft(current); // Right Right
} else {
current->right = rotateRight(current->right); // Right Left
return rotateLeft(current);
}
}
return current;
}
Node * getMin(Node * node) {
while (node->left)
node = node->left;
return node;
}
void printInorder(AVLTree * tree) {
if (!tree) return;
printInorderRecursive(tree->root);
printf("\n");
}
void printInorderRecursive(Node * current) {
if (!current) return;
printInorderRecursive(current->left);
printf("%d ", current->data);
printInorderRecursive(current->right);
}
void freeTree(Node * root) {
if (!root) return;
freeTree(root->left);
freeTree(root->right);
free(root);
}
int main() {
AVLTree * tree = malloc(sizeof(AVLTree));
tree->root = NULL;
int data[] = {90, 23, 13, 56, 84, 49, 93, 27, 64, 89, 72, 34, 13, 2, 9, 22, 72, 85, 40, 51};
int dataCount = 20;
printf(" Building AVL tree with %d possible nodes...\n\n", dataCount);
for (int i = 0; i < dataCount; i++) {
int newData = data[i];
insert(tree, newData);
}
printf("Tree successfully built. Duplicates automatically disregarded.\n");
printf("Printing tree...\n");
printInorder(tree);
// The following call will successfully delete the node with data value 90
printf("\nAttempting to delete 90...\n");
deleteNode(tree, 90);
printf("\nTree state after attempted deletion.\n");
printInorder(tree);
// The following call will successfully delete the node with data value 49
printf("\nAttempting to delete 49...\n");
deleteNode(tree, 49);
printf("\nTree state after attempted deletion.\n");
printInorder(tree);
// The following call attempts to delete 58. Since 58 is not in the tree,
// the structure remains unchanged.
printf("\nAttempting to delete 58...\n");
deleteNode(tree, 58);
printf("\nTree state after attempted deletion.\n");
printInorder(tree);
freeTree(tree->root);
free(tree);
return 0;
}
Academic Notice: The code shown here is provided solely as a learning reference. Copying and pasting is intentionally disabled to encourage independent practice. Students should implement solutions on their own to demonstrate understanding. This material is not intended for direct submission in assignments.
Additionally: This code was written by a former CS1 student and may not reflect your professor’s intended solution or instructional approach. For coursework, students are expected to follow examples, conventions, and requirements presented in class and in professor-assigned materials.