WEEK 1
Construct an AVL tree for a given set of elements which are stored in a file. And
implement insert and delete operation on the constructed tree. Write contents of tree into
a new file using in-order.
// Including necessary header files
#include <stdio.h>
#include <stdlib.h>
// Structure for a tree node
struct TreeNode {
int data;
struct TreeNode* left;
struct TreeNode* right;
int height; // Height of the node
};
// Function to get the height of a node
int height(struct TreeNode* node) {
if (node == NULL)
return 0;
return node->height;
// Function to get the maximum of two integers
int max(int a, int b) {
return (a > b) ? a : b;
}
// Function to create a new node with a given key
struct TreeNode* createNode(int key) {
struct TreeNode* newNode =malloc(sizeof(struct TreeNode));
if (newNode != NULL) {
newNode->data = key;
newNode->left = NULL;
newNode->right = NULL;
newNode->height = 1; // New node is initially at height 1
return newNode;
// Function to right rotate subtree rooted with y
struct TreeNode* rightRotate(struct TreeNode* y) {
struct TreeNode* x = y->left;
struct TreeNode* T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
// Return new root
return x;
// Function to left rotate subtree rooted with x
struct TreeNode* leftRotate(struct TreeNode* x) {
struct TreeNode* y = x->right;
struct TreeNode* T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
// Return new root
return y;
// Function to get the balance factor of a node
int getBalance(struct TreeNode* node) {
if (node == NULL)
return 0;
return height(node->left) - height(node->right);
// Function to insert a key into the AVL tree
struct TreeNode* insert(struct TreeNode* root, int key) {
// Perform standard BST insert
if (root == NULL)
return createNode(key);
if (key < root->data)
root->left = insert(root->left, key);
else if (key > root->data)
root->right = insert(root->right, key);
else // Duplicate keys not allowed
return root;
// Update height of the current node
root->height = 1 + max(height(root->left), height(root->right));
// Get the balance factor to check whether this node became unbalanced
int balance = getBalance(root);
// Left Left Case
if (balance > 1 && key < root->left->data)
return rightRotate(root);
// Right Right Case
if (balance < -1 && key > root->right->data)
return leftRotate(root);
// Left Right Case
if (balance > 1 && key > root->left->data) {
root->left = leftRotate(root->left);
return rightRotate(root);
// Right Left Case
if (balance < -1 && key < root->right->data) {
root->right = rightRotate(root->right);
return leftRotate(root);
// Return the unchanged node pointer
return root;
// Function to find the node with the minimum value
struct TreeNode* minValueNode(struct TreeNode* node) {
struct TreeNode* current = node;
while (current->left != NULL)
current = current->left;
return current;
// Function to delete a key from the AVL tree
struct TreeNode* deleteNode(struct TreeNode* root, int key) {
if (root == NULL)
return root;
// Perform standard BST delete
if (key < root->data)
root->left = deleteNode(root->left, key);
else if (key > root->data)
root->right = deleteNode(root->right, key);
else {
// Node with only one child or no child
if ((root->left == NULL) || (root->right == NULL)) {
struct TreeNode* temp = root->left ? root->left : root->right;
// No child case
if (temp == NULL) {
temp = root;
root = NULL;
} else // One child case
*root = *temp; // Copy the contents of the non-empty child
free(temp);
} else {
// Node with two children, get the inorder successor
struct TreeNode* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->data = temp->data;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->data);
// If the tree had only one node, then return
if (root == NULL)
return root;
// Update height of the current node
root->height = 1 + max(height(root->left), height(root->right));
// Get the balance factor to check whether this node became unbalanced
int balance = getBalance(root);
// Left Left Case
if (balance > 1 && getBalance(root->left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 && getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
// Right Right Case
if (balance < -1 && getBalance(root->right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 && getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
return root;
}/
// Function to perform in-order traversal of the AVL tree
void inOrderTraversal(struct TreeNode* root) {
if (root != NULL) {
inOrderTraversal(root->left);
printf("%d ", root->data);
inOrderTraversal(root->right);
// Function to free the memory allocated for the AVL tree
void freeAVLTree(struct TreeNode* root) {
if (root != NULL) {
freeAVLTree(root->left);
freeAVLTree(root->right);
free(root);
int main() {
struct TreeNode* root = NULL;
int choice, key;
do {
printf("\nAVL Tree Operations:\n");
printf("1. Insert a node\n");
printf("2. Delete a node\n");
printf("3. In-order Traversal\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the key to insert: ");
scanf("%d", &key);
root = insert(root, key);
break;
case 2:
printf("Enter the key to delete: ");
scanf("%d", &key);
root = deleteNode(root, key);
break;
case 3:
printf("In-order Traversal: ");
inOrderTraversal(root);
printf("\n");
break;
case 4:
// Free allocated memory
freeAVLTree(root);
printf("Exiting...\n");
break;
default:
printf("Invalid choice! Please enter a valid option.\n");
} while (choice != 4);
return 0;
Output:
[?2004l
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 20
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 11
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 5
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 32
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 2
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 1
Enter the key to insert: 4
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 3
In-order Traversal: 2 4 5 11 20 32 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 2
Enter the key to delete: 2
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 3
In-order Traversal: 4 5 11 20 32 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 2
Enter the key to delete: 4
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 3
In-order Traversal: 5 11 20 32 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 2
Enter the key to delete: 32
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 3
In-order Traversal: 5 11 20 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 2
Enter the key to delete: 11
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice: 3
In-order Traversal: 5 20 40
AVL Tree Operations:
1. Insert a node
2. Delete a node
3. In-order Traversal
4. Exit
Enter your choice:4
Exiting...
Week 2
2.Construct B-Tree an order of 5 with a set of 100 random elements stored in array. Implement
searching, insertion and deletion operations.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define M 5 // Maximum degree of the B-tree
struct BTreeNode {
int num_keys; // Number of keys currently in the node
int keys[M-1]; // Array of keys
struct BTreeNode *children[M]; // Array of child pointers
bool is_leaf; // True if node is a leaf
};
// Function to create a new node
struct BTreeNode *createNode(bool is_leaf) {
struct BTreeNode *newNode = (struct BTreeNode *)malloc(sizeof(struct BTreeNode));
if (newNode == NULL) {
perror("Memory allocation failed");
exit(EXIT_FAILURE);
newNode->num_keys = 0;
newNode->is_leaf = is_leaf;
for (int i = 0; i < M; i++) {
newNode->children[i] = NULL;
return newNode;
}
// Function to split a full child node
void splitChild(struct BTreeNode *parent, int index) {
struct BTreeNode *child = parent->children[index];
struct BTreeNode *newNode = createNode(child->is_leaf);
newNode->num_keys = M/2 - 1;
// Move keys and children to the new node
for (int i = 0; i < M/2 - 1; i++) {
newNode->keys[i] = child->keys[i + M/2];
if (!child->is_leaf) {
for (int i = 0; i < M/2; i++) {
newNode->children[i] = child->children[i + M/2];
child->num_keys = M/2 - 1;
// Shift parent's children to make space for the new node
for (int i = parent->num_keys; i > index; i--) {
parent->children[i + 1] = parent->children[i];
}
parent->children[index + 1] = newNode;
// Shift parent's keys to insert the middle key from the child
for (int i = parent->num_keys - 1; i >= index; i--) {
parent->keys[i + 1] = parent->keys[i];
parent->keys[index] = child->keys[M/2 - 1];
parent->num_keys++;
// Function to insert a key into a non-full node
void insertNonFull(struct BTreeNode *node, int key) {
int i = node->num_keys - 1;
if (node->is_leaf) {
// Insert key into the sorted order
while (i >= 0 && node->keys[i] > key) {
node->keys[i + 1] = node->keys[i];
i--;
node->keys[i + 1] = key;
node->num_keys++;
} else {
// Find the child to insert the key
while (i >= 0 && node->keys[i] > key) {
i--;
i++;
if (node->children[i]->num_keys == M - 1) {
// Split child if it's full
splitChild(node, i);
// Determine which of the two children is the new one
if (node->keys[i] < key) {
i++;
insertNonFull(node->children[i], key);
// Function to insert a key into the B-tree
void insert(struct BTreeNode **root, int key) {
struct BTreeNode *node = *root;
if (node == NULL) {
// Create a new root node
*root = createNode(true);
(*root)->keys[0] = key;
(*root)->num_keys = 1;
} else {
if (node->num_keys == M - 1) {
// Split the root if it's full
struct BTreeNode *new_root = createNode(false);
new_root->children[0] = node;
splitChild(new_root, 0);
*root = new_root;
insertNonFull(*root, key);
// Function to traverse and print the B-tree in-order
void traverse(struct BTreeNode *root) {
if (root != NULL) {
int i;
for (i = 0; i < root->num_keys; i++) {
traverse(root->children[i]);
printf("%d ", root->keys[i]);
traverse(root->children[i]);
}
// Main function to test B-tree implementation
int main() {
struct BTreeNode *root = NULL;
insert(&root, 10);
insert(&root, 20);
insert(&root, 5);
insert(&root, 6);
insert(&root, 12);
insert(&root, 30);
printf("In-order traversal of the B-tree: ");
traverse(root);
printf("\n");
return 0;
OUTPUT: