EXP-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 inorder.
File name:AVL_CO1.C
Source Code:
#include<stdio.h>
#include<stdlib.h>
// structure of the tree node
struct node
{
int data;
struct node* left;
struct node* right;
int ht;
};
// global initialization of root node
struct node* root = NULL;
// function prototyping
struct node* create(int);
struct node* insert(struct node*, int);
struct node* delete(struct node*, int);
struct node* search(struct node*, int);
struct node* rotate_left(struct node*);
struct node* rotate_right(struct node*);
int balance_factor(struct node*);
int height(struct node*);
void inorder(struct node*);
void preorder(struct node*);
void postorder(struct node*);
int main()
{
int user_choice, data;
char user_continue = 'y';
struct node* result = NULL;
while (user_continue == 'y' || user_continue == 'Y')
{
printf("\n\n------- AVL TREE --------\n");
printf("\n1. Insert");
printf("\n2. Delete");
printf("\n3. Search");
printf("\n4. Inorder");
printf("\n5. Preorder");
printf("\n6. Postorder");
printf("\n7. EXIT");
printf("\n\nEnter Your Choice: ");
scanf("%d", &user_choice);
switch(user_choice)
{
case 1:
printf("\nEnter data: ");
scanf("%d", &data);
root = insert(root, data);
break;
case 2:
printf("\nEnter data: ");
scanf("%d", &data);
root = delete(root, data);
break;
case 3:
printf("\nEnter data: ");
scanf("%d", &data);
result = search(root, data);
if (result == NULL)
{
printf("\nNode not found!");
}
else
{
printf("\n Node found");
}
break;
case 4:
inorder(root);
break;
case 5:
preorder(root);
break;
case 6:
postorder(root);
break;
case 7:
printf("\n\tProgram Terminated\n");
return 1;
default:
printf("\n\tInvalid Choice\n");
}
printf("\n\nDo you want to continue? ");
scanf(" %c", &user_continue);
}
return 0;
}
// creates a new tree node
struct node* create(int data)
{
struct node* new_node = (struct node*) malloc (sizeof(struct node));
// if a memory error has occurred
if (new_node == NULL)
{
printf("\nMemory can't be allocated\n");
return NULL;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
}
// rotates to the left
struct node* rotate_left(struct node* root)
{
struct node* right_child = root->right;
root->right = right_child->left;
right_child->left = root;
// update the heights of the nodes
root->ht = height(root);
right_child->ht = height(right_child);
// return the new node after rotation
return right_child;
}
// rotates to the right
struct node* rotate_right(struct node* root)
{
struct node* left_child = root->left;
root->left = left_child->right;
left_child->right = root;
// update the heights of the nodes
root->ht = height(root);
left_child->ht = height(left_child);
// return the new node after rotation
return left_child;
}
// calculates the balance factor of a node
int balance_factor(struct node* root)
{
int lh, rh;
if (root == NULL)
return 0;
if (root->left == NULL)
lh = 0;
else
lh = 1 + root->left->ht;
if (root->right == NULL)
rh = 0;
else
rh = 1 + root->right->ht;
return lh - rh;
}
// calculate the height of the node
int height(struct node* root)
{
int lh, rh;
if (root == NULL)
{
return 0;
}
if (root->left == NULL)
lh = 0;
else
lh = 1 + root->left->ht;
if (root->right == NULL)
rh = 0;
else
rh = 1 + root->right->ht;
if (lh > rh)
return (lh);
return (rh);
}
// inserts a new node in the AVL tree
struct node* insert(struct node* root, int data)
{
if (root == NULL)
{
struct node* new_node = create(data);
if (new_node == NULL)
{
return NULL;
}
root = new_node;
}
else if (data > root->data)
{
// insert the new node to the right
root->right = insert(root->right, data);
// tree is unbalanced, then rotate it
if (balance_factor(root) == -2)
{
if (data > root->right->data)
{
root = rotate_left(root);
}
else
{
root->right = rotate_right(root->right);
root = rotate_left(root);
}
}
}
else
{
// insert the new node to the left
root->left = insert(root->left, data);
// tree is unbalanced, then rotate it
if (balance_factor(root) == 2)
{
if (data < root->left->data)
{
root = rotate_right(root);
}
else
{
root->left = rotate_left(root->left);
root = rotate_right(root);
}
}
}
// update the heights of the nodes
root->ht = height(root);
return root;
}
// deletes a node from the AVL tree
struct node * delete(struct node *root, int x)
{
struct node * temp = NULL;
if (root == NULL)
{
return NULL;
}
if (x > root->data)
{
root->right = delete(root->right, x);
if (balance_factor(root) == 2)
{
if (balance_factor(root->left) >= 0)
{
root = rotate_right(root);
}
else
{
root->left = rotate_left(root->left);
root = rotate_right(root);
}
}
}
else if (x < root->data)
{
root->left = delete(root->left, x);
if (balance_factor(root) == -2)
{
if (balance_factor(root->right) <= 0)
{
root = rotate_left(root);
}
else
{
root->right = rotate_right(root->right);
root = rotate_left(root);
}
}
}
else
{
if (root->right != NULL)
{
temp = root->right;
while (temp->left != NULL)
temp = temp->left;
root->data = temp->data;
root->right = delete(root->right, temp->data);
if (balance_factor(root) == 2)
{
if (balance_factor(root->left) >= 0)
{
root = rotate_right(root);
}
else
{
root->left = rotate_left(root->left);
root = rotate_right(root);
}
}
}
else
{
return (root->left);
}
}
root->ht = height(root);
return (root);
}
// search a node in the AVL tree
struct node* search(struct node* root, int key)
{
if (root == NULL)
{
return NULL;
}
if(root->data == key)
{
return root;
}
if(key > root->data)
{
search(root->right, key);
}
else
{
search(root->left, key);
}
}
// inorder traversal of the tree
void inorder(struct node* root)
{
if (root == NULL)
{
return ;
}
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
// preorder traversal of the tree
void preorder(struct node* root)
{
if (root == NULL)
{
return;
}
printf("%d ", root->data);
preorder(root->left);
preorder(root->right);
}
// postorder traversal of the tree
void postorder(struct node* root)
{
if (root == NULL)
{
return;
}
postorder(root->left);
postorder(root->right);
printf("%d ", root->data);
return 0;
}
EXPERIMENT-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 <time.h>
#define T 5 // Order of the B-Tree
typedef struct BTreeNode {
int keys[2 * T - 1];
struct BTreeNode *children[2 * T];
int n; // Current number of keys
int leaf; // 1 if leaf, 0 otherwise
} BTreeNode;
typedef struct BTree {
BTreeNode *root;
} BTree;
BTreeNode* createNode(int leaf) {
BTreeNode *newNode = (BTreeNode *)malloc(sizeof(BTreeNode));
newNode->leaf = leaf;
newNode->n = 0;
return newNode;
}
BTree* createBTree() {
BTree *bTree = (BTree *)malloc(sizeof(BTree));
bTree->root = createNode(1);
return bTree;
}
void splitChild(BTreeNode *parent, int i, BTreeNode *child) {
int j;
BTreeNode *newNode = createNode(child->leaf);
newNode->n = T - 1;
for (j = 0; j < T - 1; j++)
newNode->keys[j] = child->keys[j + T];
if (!child->leaf) {
for (j = 0; j < T; j++)
newNode->children[j] = child->children[j + T];
}
child->n = T - 1;
for (j = parent->n; j >= i + 1; j--)
parent->children[j + 1] = parent->children[j];
parent->children[i + 1] = newNode;
for (j = parent->n - 1; j >= i; j--)
parent->keys[j + 1] = parent->keys[j];
parent->keys[i] = child->keys[T - 1];
parent->n++;
}
void insertNonFull(BTreeNode *node, int k) {
int i = node->n - 1;
if (node->leaf) {
while (i >= 0 && k < node->keys[i]) {
node->keys[i + 1] = node->keys[i];
i--;
}
node->keys[i + 1] = k;
node->n++;
} else {
while (i >= 0 && k < node->keys[i])
i--;
i++;
if (node->children[i]->n == 2 * T - 1) {
splitChild(node, i, node->children[i]);
if (k > node->keys[i])
i++;
}
insertNonFull(node->children[i], k);
}
}
void insert(BTree *bTree, int k) {
BTreeNode *root = bTree->root;
if (root->n == 2 * T - 1) {
BTreeNode *newNode = createNode(0);
newNode->children[0] = root;
splitChild(newNode, 0, root);
bTree->root = newNode;
insertNonFull(newNode, k);
} else {
insertNonFull(root, k);
}
}
void merge(BTreeNode *node, int idx) {
BTreeNode *child = node->children[idx];
BTreeNode *sibling = node->children[idx + 1];
int i;
child->keys[T - 1] = node->keys[idx];
for (i = 0; i < sibling->n; i++)
child->keys[i + T] = sibling->keys[i];
if (!child->leaf) {
for (i = 0; i <= sibling->n; i++)
child->children[i + T] = sibling->children[i];
}
for (i = idx + 1; i < node->n; i++)
node->keys[i - 1] = node->keys[i];
for (i = idx + 2; i <= node->n; i++)
node->children[i - 1] = node->children[i];
child->n += sibling->n + 1;
node->n--;
free(sibling);
}
void fill(BTreeNode *node, int idx) {
if (idx != 0 && node->children[idx - 1]->n >= T) {
BTreeNode *child = node->children[idx];
BTreeNode *sibling = node->children[idx - 1];
int i;
for (i = child->n - 1; i >= 0; i--)
child->keys[i + 1] = child->keys[i];
if (!child->leaf) {
for (i = child->n; i >= 0; i--)
child->children[i + 1] = child->children[i];
}
child->keys[0] = node->keys[idx - 1];
if (!child->leaf)
child->children[0] = sibling->children[sibling->n];
node->keys[idx - 1] = sibling->keys[sibling->n - 1];
child->n++;
sibling->n--;
} else if (idx != node->n && node->children[idx + 1]->n >= T) {
BTreeNode *child = node->children[idx];
BTreeNode *sibling = node->children[idx + 1];
child->keys[child->n] = node->keys[idx];
if (!child->leaf)
child->children[child->n + 1] = sibling->children[0];
node->keys[idx] = sibling->keys[0];
int i;
for (i = 1; i < sibling->n; i++)
sibling->keys[i - 1] = sibling->keys[i];
if (!sibling->leaf) {
for (i = 1; i <= sibling->n; i++)
sibling->children[i - 1] = sibling->children[i];
}
child->n++;
sibling->n--;
} else {
if (idx != node->n) {
merge(node, idx);
} else {
merge(node, idx - 1);
}
}
}
void deleteKey(BTree *bTree, BTreeNode *node, int k) {
int i,idx = 0;
while (idx < node->n && node->keys[idx] < k)
idx++;
if (idx < node->n && node->keys[idx] == k) {
if (node->leaf) {
for (i = idx + 1; i < node->n; i++)
node->keys[i - 1] = node->keys[i];
node->n--;
} else {
// Handle deletion from internal node
// (Implement successor and predecessor logic)
// ... (Code for deleting from internal nodes)
}
} else {
if (node->leaf) {
printf("The key %d is not present in the tree\n", k);
return;
}
int flag = (idx == node->n);
if (node->children[idx]->n < T)
fill(node, idx);
if (flag && idx > node->n)
deleteKey(bTree, node->children[idx - 1], k);
else
deleteKey(bTree, node->children[idx], k);
}
}
int search(BTreeNode *node, int k) {
int i = 0;
while (i < node->n && k > node->keys[i])
i++;
if (i < node->n && k == node->keys[i])
return 1;
if (node->leaf)
return 0;
return search(node->children[i], k);
}
void printBTree(BTreeNode *node, int level) {
int i;
if (node) {
printf("Level %d: ", level);
for (i = 0; i < node->n; i++)
printf("%d ", node->keys[i]);
printf("\n");
for (i = 0; i <= node->n; i++)
printBTree(node->children[i], level + 1);
}
}
int main() {
srand(time(0));
BTree *bTree = createBTree();
int elements[100];
int i,k;
// Generate 100 random elements
for (i = 0; i < 100; i++) {
elements[i] = rand() % 200 + 1; // Random numbers between 1 and 200
insert(bTree, elements[i]);
}
printf("B-Tree after insertion:\n");
printBTree(bTree->root, 0);
// Search for a random key
int searchKey = elements[rand() % 100];
printf("Searching for %d: %s\n", searchKey, search(bTree->root, searchKey) ?
"Found" : "Not Found");
// Delete a random key
int deleteKeyValue = elements[rand() % 100];
printf("Deleting %d\n", deleteKeyValue);
deleteKey(bTree, bTree->root,k);
}