0% found this document useful (0 votes)
12 views

ADS

The document provides source code for constructing an AVL tree and a B-tree, including implementations for insertion, deletion, and in-order traversal. The AVL tree maintains balance through rotations during insertions and deletions, while the B-tree manages keys in nodes and allows for efficient searching and merging of nodes. Both data structures are demonstrated with operations on random elements, showcasing their functionality.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

ADS

The document provides source code for constructing an AVL tree and a B-tree, including implementations for insertion, deletion, and in-order traversal. The AVL tree maintains balance through rotations during insertions and deletions, while the B-tree manages keys in nodes and allows for efficient searching and merging of nodes. Both data structures are demonstrated with operations on random elements, showcasing their functionality.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 62

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.

SOURCE CODE:

// 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 = (struct TreeNode*)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:
2. Construct B-Tree an order of 5 with a set of 100 random elements stored in array.

Implement searching, insertion and deletion operations.

SOURCE CODE:

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>
#define T 3 // Minimum degree for B-Tree of order 5

typedef struct BTreeNode {

int *keys;

struct BTreeNode **children;

int n; // Number of keys

bool leaf;

} BTreeNode;

void deleteKey(BTreeNode *node, int key);

void borrowFromPrev(BTreeNode *node, int idx);

void borrowFromNext(BTreeNode *node, int idx);

int getPredecessor(BTreeNode *node) {

BTreeNode *cur = node;

while (!cur->leaf)

cur = cur->children[cur->n];

return cur->keys[cur->n - 1];

int getSuccessor(BTreeNode *node) {

BTreeNode *cur = node;

while (!cur->leaf)

cur = cur->children[0];

return cur->keys[0];

int findKey(BTreeNode *node, int key) {

int idx = 0;

while (idx < node->n && node->keys[idx] < key)

idx++;

return idx;

}
BTreeNode* createNode(bool leaf) {

BTreeNode *node = (BTreeNode *)malloc(sizeof(BTreeNode));

node->keys = (int *)malloc((2 * T - 1) * sizeof(int));

node->children = (BTreeNode **)malloc(2 * T * sizeof(BTreeNode *));

node->n = 0;

node->leaf = leaf;

return node;

void merge(BTreeNode *node, int idx) {

BTreeNode *child = node->children[idx];

BTreeNode *sibling = node->children[idx + 1];

child->keys[T - 1] = node->keys[idx];

int i;

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->children[i] = node->children[i + 1];

for (i = idx; i < node->n - 1; i++)

node->keys[i] = node->keys[i + 1];

child->n += sibling->n + 1;

node->n--;

free(sibling->keys);
free(sibling->children);

free(sibling);

void traverse(BTreeNode *root, int level) {

int i;

if (root != NULL) {

printf("Level %d: ", level);

for (i = 0; i < root->n; i++)

printf("%d ", root->keys[i]);

printf("\n");

if (!root->leaf) {

for(i = 0; i <= root->n; i++)

traverse(root->children[i], level + 1);

void splitChild(BTreeNode *parent, int i) {

BTreeNode *fullChild = parent->children[i];

BTreeNode *newChild = createNode(fullChild->leaf);

parent->children[i + 1] = newChild;

parent->keys[i] = fullChild->keys[T - 1];

newChild->n = T - 1;

fullChild->n = T - 1;

int j;

for (j = 0; j < T - 1; j++)

newChild->keys[j] = fullChild->keys[j + T];

if (!fullChild->leaf) {

for (j = 0; j < T; j++)

newChild->children[j] = fullChild->children[j + T];

}
for (j = parent->n; j > i; j--)

parent->children[j + 1] = parent->children[j];

parent->children[i] = fullChild;

parent->n++;

void insertNonFull(BTreeNode *node, int key) {

int i = node->n - 1;

if (node->leaf) {

while (i >= 0 && key < node->keys[i]) {

node->keys[i + 1] = node->keys[i];

i--;

node->keys[i + 1] = key;

node->n++;

} else {

while (i >= 0 && key < node->keys[i])

i--;

i++;

if (node->children[i]->n == 2 * T - 1) {

splitChild(node, i);

if (key > node->keys[i])

i++;

insertNonFull(node->children[i], key);

void insert(BTreeNode **root, int key) {

BTreeNode *r = *root;

if (r->n == 2 * T - 1) {
BTreeNode *s = createNode(false);

*root = s;

s->children[0] = r;

splitChild(s, 0);

insertNonFull(s, key);

} else {

insertNonFull(r, key);

bool search(BTreeNode *root, int key) {

int i = 0;

while (i < root->n && key > root->keys[i])

i++;

if (i < root->n && root->keys[i] == key)

return true;

if (root->leaf)

return false;

return search(root->children[i], key);

void removeFromNonLeaf(BTreeNode *node, int idx) {

int key = node->keys[idx];

if (node->children[idx]->n >= T) {

int pred = getPredecessor(node->children[idx]);

node->keys[idx] = pred;

deleteKey(node->children[idx], pred);

} else if (node->children[idx + 1]->n >= T) {

int succ = getSuccessor(node->children[idx + 1]);

node->keys[idx] = succ;

deleteKey(node->children[idx + 1], succ);

} else {

merge(node, idx);

deleteKey(node->children[idx], key);

}
}

void removeFromLeaf(BTreeNode *node, int idx) {

int i;

for (i = idx + 1; i < node->n; i++)

node->keys[i - 1] = node->keys[i];

node->n--;

void fill(BTreeNode *node, int idx) {

if (idx != 0 && node->children[idx - 1]->n >= T)

borrowFromPrev(node, idx);

else if (idx != node->n && node->children[idx + 1]->n >= T)

borrowFromNext(node, idx);

else {

if (idx != node->n)

merge(node, idx);

else

merge(node, idx - 1);

void borrowFromPrev(BTreeNode *node, int idx) {

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 (!node->leaf)

child->children[0] = sibling->children[sibling->n];

node->keys[idx - 1] = sibling->keys[sibling->n - 1];


child->n++;

sibling->n--;

void borrowFromNext(BTreeNode *node, int idx) {

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--;

void deleteKey(BTreeNode *node, int key) {

int idx = findKey(node, key);

if (idx < node->n && node->keys[idx] == key) {

if (node->leaf)

removeFromLeaf(node, idx);

else

removeFromNonLeaf(node, idx);

} else {

if (node->leaf) {

printf("The key %d is not present in the tree\n", key);

return;

bool flag = ((idx == node->n) ? true : false);


if (node->children[idx]->n < T)

fill(node, idx);

if (flag && idx > node->n)

deleteKey(node->children[idx - 1], key);

else

deleteKey(node->children[idx], key);

int main() {

BTreeNode *root = createNode(true);

int i;

// Insert 100 random elements

for (i = 0; i < 100; i++) {

int key = rand() % 1000;

printf("Inserting %d\n", key);

insert(&root, key);

// Traverse and print the B-Tree

printf("B-Tree structure:\n");

traverse(root, 0);

// Search for a random element

int keyToSearch = rand() % 1000;

printf("Searching for %d: %s\n", keyToSearch, search(root, keyToSearch) ? "Found" : "Not


found");

// Delete a random element

int keyToDelete = rand() % 1000;

printf("Deleting %d\n", keyToDelete);

deleteKey(root, keyToDelete);

// Traverse and print the B-Tree after deletion

printf("B-Tree structure after deletion:\n");

traverse(root, 0);

return 0;

}
OUTPUT:

3. Construct Min and Max Heap using arrays, delete any element and display the content
of the Heap.

SOURCE CODE:

Max Heap:

#include <stdio.h>

#include <stdlib.h>

#define MAX_SIZE 100

typedef struct {

int arr[MAX_SIZE];

int size;

} MaxHeap;
void swap(int *a, int *b) {

int temp = *a;

*a = *b;

*b = temp;

void maxHeapify(MaxHeap *heap, int idx) {

int largest = idx;

int left = 2 * idx + 1;

int right = 2 * idx + 2;

if (left < heap->size && heap->arr[left] > heap->arr[largest])

largest = left;

if (right < heap->size && heap->arr[right] > heap->arr[largest])

largest = right;

if (largest != idx) {

swap(&heap->arr[idx], &heap->arr[largest]);

maxHeapify(heap, largest);

void insertMaxHeap(MaxHeap *heap, int key) {

if (heap->size == MAX_SIZE) {

printf("Heap overflow\n");

return;

int idx = heap->size++;

heap->arr[idx] = key;

while (idx != 0 && heap->arr[idx] > heap->arr[(idx - 1) / 2]) {

swap(&heap->arr[idx], &heap->arr[(idx - 1) / 2]);

idx = (idx - 1) / 2;
}

void deleteMaxHeap(MaxHeap *heap) {

if (heap->size <= 0) {

printf("Heap is empty\n");

return;

if (heap->size == 1) {

heap->size--;

return;

heap->arr[0] = heap->arr[heap->size - 1];

heap->size--;

maxHeapify(heap, 0);

void displayMaxHeap(MaxHeap *heap) {

int i;

for (i = 0; i < heap->size; i++)

printf("%d ", heap->arr[i]);

printf("\n");

int main() {

MaxHeap heap;

heap.size = 0;

insertMaxHeap(&heap, 3);

insertMaxHeap(&heap, 2);

insertMaxHeap(&heap, 15);

insertMaxHeap(&heap, 5);
insertMaxHeap(&heap, 4);

insertMaxHeap(&heap, 45);

printf("Max-Heap: ");

displayMaxHeap(&heap);

printf("Deleting root...\n");

deleteMaxHeap(&heap);

printf("Max-Heap after deletion: ");

displayMaxHeap(&heap);

return 0;

OUTPUT:

MIN HEAP:

#include <stdio.h>

#include <stdlib.h>

#define MAX_SIZE 100

typedef struct {

int arr[MAX_SIZE];

int size;

} MinHeap;
void swap(int *a, int *b) {

int temp = *a;

*a = *b;

*b = temp;

void minHeapify(MinHeap *heap, int idx) {

int smallest = idx;

int left = 2 * idx + 1;

int right = 2 * idx + 2;

if (left < heap->size && heap->arr[left] < heap->arr[smallest])

smallest = left;

if (right < heap->size && heap->arr[right] < heap->arr[smallest])

smallest = right;

if (smallest != idx) {

swap(&heap->arr[idx], &heap->arr[smallest]);

minHeapify(heap, smallest);

void insertMinHeap(MinHeap *heap, int key) {

if (heap->size == MAX_SIZE) {

printf("Heap overflow\n");

return;

int idx = heap->size++;

heap->arr[idx] = key;

while (idx != 0 && heap->arr[idx] < heap->arr[(idx - 1) / 2]) {

swap(&heap->arr[idx], &heap->arr[(idx - 1) / 2]);

idx = (idx - 1) / 2;
}

void deleteMinHeap(MinHeap *heap) {

if (heap->size <= 0) {

printf("Heap is empty\n");

return;

if (heap->size == 1) {

heap->size--;

return;

heap->arr[0] = heap->arr[heap->size - 1];

heap->size--;

minHeapify(heap, 0);

void displayMinHeap(MinHeap *heap) {

int i;

for (i = 0; i < heap->size; i++)

printf("%d ", heap->arr[i]);

printf("\n");

int main() {

MinHeap heap;

heap.size = 0;

insertMinHeap(&heap, 3);

insertMinHeap(&heap, 2);

insertMinHeap(&heap, 15);

insertMinHeap(&heap, 5);
insertMinHeap(&heap, 4);

insertMinHeap(&heap, 45);

printf("Min-Heap: ");

displayMinHeap(&heap);

printf("Deleting root...\n");

deleteMinHeap(&heap);

printf("Min-Heap after deletion: ");

displayMinHeap(&heap);

return 0;

OUTPUT:

4. Implement BFT and DFT for given graph, when graph is represented by

a) Adjacency Matrix b) Adjacency Lists

SOURCE CODE:

//Breadth-First Traversal (BFT) using Adjacency Matrix

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

int adjMatrix[MAX][MAX];

int visited[MAX];

int queue[MAX];
int front = -1, rear = -1;

void enqueue(int vertex) {

if (rear == MAX - 1)

return;

if (front == -1)

front = 0;

queue[++rear] = vertex;

int dequeue() {

if (front == -1 || front > rear)

return -1;

return queue[front++];

void BFT(int startVertex, int n) {

int i;

enqueue(startVertex);

visited[startVertex] = 1;

while (front <= rear) {

int currentVertex = dequeue();

printf("%d ", currentVertex);

for (i = 0; i < n; i++) {

if (adjMatrix[currentVertex][i] == 1 && !visited[i]) {

enqueue(i);

visited[i] = 1;

int main() {
int n, i, j, startVertex;

printf("Enter number of vertices: ");

scanf("%d", &n);

printf("Enter the adjacency matrix:\n");

for (i = 0; i < n; i++) {

for (j = 0; j < n; j++) {

scanf("%d", &adjMatrix[i][j]);

printf("Enter the starting vertex: ");

scanf("%d", &startVertex);

printf("Breadth First Traversal starting from vertex %d: ", startVertex);

BFT(startVertex, n);

return 0;

OUTPUT:

//Depth-First Traversal (DFT) using Adjacency Matrix

#include <stdio.h>

#include <stdlib.h>

#define MAX 100


int adjMatrix[MAX][MAX];

int visited[MAX];

void DFT(int vertex, int n) {

int i;

printf("%d ", vertex);

visited[vertex] = 1;

for (i = 0; i < n; i++) {

if (adjMatrix[vertex][i] == 1 && !visited[i]) {

DFT(i, n);

int main() {

int n, i, j, startVertex;

printf("Enter number of vertices: ");

scanf("%d", &n);

printf("Enter the adjacency matrix:\n");

for (i = 0; i < n; i++) {

for (j = 0; j < n; j++) {

scanf("%d", &adjMatrix[i][j]);

printf("Enter the starting vertex: ");

scanf("%d", &startVertex);

printf("Depth First Traversal starting from vertex %d: ", startVertex);

DFT(startVertex, n);

return 0;
}

OUTPUT:

//Breadth-First Traversal (BFT) using Adjacency List

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

typedef struct Node {

int vertex;

struct Node* next;

} Node;

Node* adjList[MAX];

int visited[MAX];

int queue[MAX];

int front = -1, rear = -1;

Node* createNode(int v) {

Node* newNode = malloc(sizeof(Node));

newNode->vertex = v;

newNode->next = NULL;

return newNode;

void addEdge(int src, int dest) {


Node* newNode = createNode(dest);

newNode->next = adjList[src];

adjList[src] = newNode;

newNode = createNode(src);

newNode->next = adjList[dest];

adjList[dest] = newNode;

void enqueue(int vertex) {

if (rear == MAX - 1)

return;

if (front == -1)

front = 0;

queue[++rear] = vertex;

int dequeue() {

if (front == -1 || front > rear)

return -1;

return queue[front++];

void BFT(int startVertex) {

int i;

enqueue(startVertex);

visited[startVertex] = 1;

while (front <= rear) {

int currentVertex = dequeue();

printf("%d ", currentVertex);

Node* temp = adjList[currentVertex];

while (temp) {

int adjVertex = temp->vertex;


if (!visited[adjVertex]) {

enqueue(adjVertex);

visited[adjVertex] = 1;

temp = temp->next;

int main() {

int n, i, src, dest, startVertex;

printf("Enter number of vertices: ");

scanf("%d", &n);

for (i = 0; i < n; i++) {

adjList[i] = NULL;

printf("Enter edges (source destination). Enter -1 -1 to stop:\n");

while (1) {

scanf("%d %d", &src, &dest);

if (src == -1 && dest == -1)

break;

addEdge(src, dest);

printf("Enter the starting vertex: ");

scanf("%d", &startVertex);

printf("Breadth First Traversal starting from vertex %d: ", startVertex);

BFT(startVertex);

return 0;
}

OUTPUT:

//Depth-First Traversal (DFT) using Adjacency List

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

typedef struct Node {

int vertex;

struct Node* next;

} Node;

Node* adjList[MAX];

int visited[MAX];

Node* createNode(int v) {

Node* newNode = malloc(sizeof(Node));

newNode->vertex = v;

newNode->next = NULL;

return newNode;

void addEdge(int src, int dest) {


Node* newNode = createNode(dest);

newNode->next = adjList[src];

adjList[src] = newNode;

newNode = createNode(src);

newNode->next = adjList[dest];

adjList[dest] = newNode;

void DFT(int vertex) {

Node* adjListPtr = adjList[vertex];

Node* temp = adjListPtr;

printf("%d ", vertex);

visited[vertex] = 1;

while (temp != NULL) {

int connectedVertex = temp->vertex;

if (visited[connectedVertex] == 0) {

DFT(connectedVertex);

temp = temp->next;

int main() {

int n, i, src, dest, startVertex;

printf("Enter number of vertices: ");

scanf("%d", &n);

for (i = 0; i < n; i++) {

adjList[i] = NULL;
}

printf("Enter edges (source destination). Enter -1 -1 to stop:\n");

while (1) {

scanf("%d %d", &src, &dest);

if (src == -1 && dest == -1)

break;

addEdge(src, dest);

printf("Enter the starting vertex: ");

scanf("%d", &startVertex);

printf("Depth First Traversal starting from vertex %d: ", startVertex);

DFT(startVertex);

return 0;

OUTPUT:

5. Write a program for finding the bi-connected components in a given graph.

SOURCE CODE:

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#define MAX 100


typedef struct Node {

int vertex;

struct Node* next;

} Node;

Node* adjList[MAX];

int disc[MAX], low[MAX], parent[MAX];

bool visited[MAX];

int timeCounter;

Node* stack[MAX];

int stackTop = -1;

Node* createNode(int v) {

Node* newNode = (Node*)malloc(sizeof(Node));

newNode->vertex = v;

newNode->next = NULL;

return newNode;

void addEdge(int src, int dest) {

Node* newNode = createNode(dest);

newNode->next = adjList[src];

adjList[src] = newNode;

newNode = createNode(src);

newNode->next = adjList[dest];

adjList[dest] = newNode;

void push(Node* node) {

stack[++stackTop] = node;

}
Node* pop() {

if (stackTop == -1)

return NULL;

return stack[stackTop--];

void printBiconnectedComponent(Node* node, int u, int v) {

printf("Biconnected component: ");

while (node != NULL && !(node->vertex == u && stack[stackTop]->vertex == v)) {

printf("(%d, %d) ", stack[stackTop]->vertex, node->vertex);

pop();

node = pop();

if (node != NULL)

printf("(%d, %d) ", node->vertex, stack[stackTop]->vertex);

printf("\n");

void findBiconnectedComponents(int u) {

static int time = 0;

disc[u] = low[u] = ++time;

visited[u] = true;

int children = 0;

Node* adjListPtr = adjList[u];

while (adjListPtr != NULL) {

int v = adjListPtr->vertex;

if (!visited[v]) {

children++;

parent[v] = u;

push(adjListPtr);

findBiconnectedComponents(v);
low[u] = (low[u] < low[v]) ? low[u] : low[v];

if ((parent[u] == -1 && children > 1) || (parent[u] != -1 && low[v] >= disc[u])) {

printBiconnectedComponent(adjListPtr, u, v);

} else if (v != parent[u] && disc[v] < disc[u]) {

low[u] = (low[u] < disc[v]) ? low[u] : disc[v];

push(adjListPtr);

adjListPtr = adjListPtr->next;

int main() {

int n, src, dest,i;

printf("Enter number of vertices: ");

scanf("%d", &n);

for (i = 0; i < n; i++) {

adjList[i] = NULL;

disc[i] = low[i] = parent[i] = -1;

visited[i] = false;

printf("Enter edges (source destination). Enter -1 -1 to stop:\n");

while (1) {

scanf("%d %d", &src, &dest);

if (src == -1 && dest == -1)

break;

addEdge(src, dest);

for (i = 0; i < n; i++) {

if (!visited[i]) {
findBiconnectedComponents(i);

return 0;

OUTPUT:

6. Implement Quick sort and Merge sort and observe the execution time for various

input sizes (Average, Worst and Best cases).

SOURCE CODE:

//MERGE SORT

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

// Function to generate an array with random integers

void generateArray(int arr[], int size) {

int i;

for (i = 0; i < size; i++) {

arr[i] = rand() % 1000000; // Random integers between 0 and 9999

// Function to print an array


void printArray(int arr[], int size) {

int i;

for (i = 0; i < size; i++) {

printf("%d ", arr[i]);

printf("\n");

void merge(int arr[], int l, int m, int r) {

int n1 = m - l + 1;

int n2 = r - m;

int i,j;

int *L = (int *)malloc(n1 * sizeof(int));

int *R = (int *)malloc(n2 * sizeof(int));

for (i = 0; i < n1; i++)

L[i] = arr[l + i];

for (j = 0; j < n2; j++)

R[j] = arr[m + 1 + j];

int k = l;

while (i < n1 && j < n2) {

if (L[i] <= R[j]) {

arr[k++] = L[i++];

} else {

arr[k++] = R[j++];

while (i < n1) {

arr[k++] = L[i++];

while (j < n2) {

arr[k++] = R[j++];
}

free(L);

free(R);

void mergeSort(int arr[], int l, int r) {

if (l < r) {

int m = l + (r - l) / 2;

mergeSort(arr, l, m);

mergeSort(arr, m + 1, r);

merge(arr, l, m, r);

// Main function

int main() {

srand(time(NULL)); // Seed for random number generation

int i;

int sizes[] = {10000, 50000, 1000000}; // Different sizes of arrays

int numSizes = sizeof(sizes) / sizeof(sizes[0]);

for (i = 0; i < numSizes; i++) {

int size = sizes[i];

int *arr1 = (int *)malloc(size * sizeof(int));

generateArray(arr1, size);

clock_t start, end;

double cpu_time_used;

// Measure Merge Sort time

start = clock();

mergeSort(arr1, 0, size - 1);

end = clock();
cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;

printf("Merge Sort time for size %d: %f seconds\n", size, cpu_time_used);

free(arr1);

return 0;

OUTPUT:

//QUICK SORT

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

void swap(int *a, int *b) {

int temp = *a;

*a = *b;

*b = temp;

int partition(int arr[], int low, int high) {

int pivot = arr[high];

int i = low - 1;

int j;
for (j = low; j < high; j++) {

if (arr[j] < pivot) {

i++;

swap(&arr[i], &arr[j]);

swap(&arr[i + 1], &arr[high]);

return i + 1;

void quickSort(int arr[], int low, int high) {

if (low < high) {

int pi = partition(arr, low, high);

quickSort(arr, low, pi - 1);

quickSort(arr, pi + 1, high);

// Function to generate an array with random integers

void generateArray(int arr[], int size) {

int i;

for (i = 0; i < size; i++) {

arr[i] = rand() % 100000; // Random integers between 0 and 9999

// Function to print an array

void printArray(int arr[], int size) {

int i;

for ( i = 0; i < size; i++) {

printf("%d ", arr[i]);

printf("\n");
}

// Main function

int main() {

srand(time(NULL)); // Seed for random number generation

int sizes[] = {10000, 50000, 100000}; // Different sizes of arrays

int numSizes = sizeof(sizes) / sizeof(sizes[0]);

int i;

for (i = 0; i < numSizes; i++) {

int size = sizes[i];

int *arr1 = (int *)malloc(size * sizeof(int));

generateArray(arr1, size);

clock_t start, end;

double cpu_time_used;

// Measure Quick Sort time

start = clock();

quickSort(arr1, 0, size - 1);

end = clock();

cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;

printf("Quick Sort time for size %d: %f seconds\n", size, cpu_time_used);

free(arr1);

getchar();

return 0;

OUTPUT:
7. Compare the performance of Single Source Shortest Paths using Greedy method when

the graph is represented by adjacency matrix and adjacency lists.

SOURCE CODE:

// C program for Dijkstra's single source shortest path

// algorithm. The program is for adjacency matrix

// representation of the graph

#include <limits.h>

#include <stdbool.h>

#include <stdio.h>

// Number of vertices in the graph

#define V 9

// A utility function to find the vertex with minimum

// distance value, from the set of vertices not yet included

// in shortest path tree

int minDistance(int dist[], bool sptSet[])

// Initialize min value

int min = INT_MAX, min_index;


for (int v = 0; v < V; v++)

if (sptSet[v] == false && dist[v] <= min)

min = dist[v], min_index = v;

return min_index;

// A utility function to print the constructed distance

// array

void printSolution(int dist[])

printf("Vertex \t\t Distance from Source\n");

for (int i = 0; i < V; i++)

printf("%d \t\t\t\t %d\n", i, dist[i]);

// Function that implements Dijkstra's single source

// shortest path algorithm for a graph represented using

// adjacency matrix representation

void dijkstra(int graph[V][V], int src)

int dist[V]; // The output array. dist[i] will hold the

// shortest

// distance from src to i

bool sptSet[V]; // sptSet[i] will be true if vertex i is

// included in shortest

// path tree or shortest distance from src to i is

// finalized

// Initialize all distances as INFINITE and stpSet[] as

// false

for (int i = 0; i < V; i++)


dist[i] = INT_MAX, sptSet[i] = false;

// Distance of source vertex from itself is always 0

dist[src] = 0;

// Find shortest path for all vertices

for (int count = 0; count < V - 1; count++) {

// Pick the minimum distance vertex from the set of

// vertices not yet processed. u is always equal to

// src in the first iteration.

int u = minDistance(dist, sptSet);

// Mark the picked vertex as processed

sptSet[u] = true;

// Update dist value of the adjacent vertices of the

// picked vertex.

for (int v = 0; v < V; v++)

// Update dist[v] only if is not in sptSet,

// there is an edge from u to v, and total

// weight of path from src to v through u is

// smaller than current value of dist[v]

if (!sptSet[v] && graph[u][v]

&& dist[u] != INT_MAX

&& dist[u] + graph[u][v] < dist[v])

dist[v] = dist[u] + graph[u][v];

// print the constructed distance array

printSolution(dist);

}
// driver's code

int main()

/* Let us create the example graph discussed above */

int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },

{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },

{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },

{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },

{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },

{ 0, 0, 4, 14, 10, 0, 2, 0, 0 },

{ 0, 0, 0, 0, 0, 2, 0, 1, 6 },

{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },

{ 0, 0, 2, 0, 0, 0, 6, 7, 0 } };

// Function call

dijkstra(graph, 0);

return 0;

OUTPUT:

8. Implement Job sequencing with deadlines using Greedy strategy.

SOURCE CODE:
#include <stdio.h>

#include <stdlib.h>

#define MAX_JOBS 100

typedef struct {

int id;

int deadline;

int profit;

} Job;

// Function to compare two jobs based on their profit

int compareJobs(const void *a, const void *b) {

return ((Job *)b)->profit - ((Job *)a)->profit;

// Function to find the maximum profit job sequence

void jobSequencing(Job jobs[], int n) {

int i,j;

// Sort jobs in decreasing order of profit

qsort(jobs, n, sizeof(Job), compareJobs);

// Array to keep track of free time slots

int result[n];

// Initialize all slots as free

for (i = 0; i < n; i++) {

result[i] = -1;

// Iterate over sorted jobs

for (i = 0; i < n; i++) {

// Find a free slot for this job

for (j = jobs[i].deadline - 1; j >= 0; j--) {


if (result[j] == -1) {

result[j] = i; // Schedule this job

break;

// Print the scheduled jobs and total profit

int totalProfit = 0;

printf("Scheduled Jobs:\n");

for (i = 0; i < n; i++) {

if (result[i] != -1) {

printf("Job ID: %d, Deadline: %d, Profit: %d\n",

jobs[result[i]].id,

jobs[result[i]].deadline,

jobs[result[i]].profit);

totalProfit += jobs[result[i]].profit;

printf("Total Profit: %d\n", totalProfit);

int main() {

int n,i;

printf("Enter the number of jobs: ");

scanf("%d", &n);

Job jobs[n];

printf("Enter job details (id, deadline, profit) for each job:\n");

for (i = 0; i < n; i++) {

printf("Job %d: ", i + 1);

scanf("%d %d %d", &jobs[i].id, &jobs[i].deadline, &jobs[i].profit);

jobSequencing(jobs, n);

return 0;

}
OUTPUT:

9. Write a program to solve 0/1 Knapsack problem Using Dynamic Programming.

SOURCE CODE:

/* A Naive recursive implementation

of 0-1 Knapsack problem */

#include <stdio.h>

// A utility function that returns

// maximum of two integers

int max(int a, int b) { return (a > b) ? a : b; }

// Returns the maximum value that can be

// put in a knapsack of capacity W

int knapSack(int W, int wt[], int val[], int n)

// Base Case

if (n == 0 || W == 0)

return 0;

// If weight of the nth item is more than


// Knapsack capacity W, then this item cannot

// be included in the optimal solution

if (wt[n - 1] > W)

return knapSack(W, wt, val, n - 1);

// Return the maximum of two cases:

// (1) nth item included

// (2) not included

else

return max(

val[n - 1]

+ knapSack(W - wt[n - 1], wt, val, n - 1),

knapSack(W, wt, val, n - 1));

// Driver code

int main()

int profit[] = { 60, 100, 120 };

int weight[] = { 10, 20, 30 };

int W = 50;

int n = sizeof(profit) / sizeof(profit[0]);

printf("%d", knapSack(W, weight, profit, n));

return 0;

OUTPUT:

10. Implement N-Queens Problem Using Backtracking.


SOURCE CODE

#define N 4

#include <stdbool.h>

#include <stdio.h>

// A utility function to print solution

void printSolution(int board[N][N])

{int i,j;

for (i = 0; i < N; i++) {

for (j = 0; j < N; j++) {

if(board[i][j])

printf("Q ");

else

printf(". ");

printf("\n");

bool isSafe(int board[N][N], int row, int col)

int i, j;

// Check this row on left side

for (i = 0; i < col; i++)

if (board[row][i])

return false;

// Check upper diagonal on left side

for (i = row, j = col; i >= 0 && j >= 0; i--, j--)

if (board[i][j])

return false;
// Check lower diagonal on left side

for (i = row, j = col; j >= 0 && i < N; i++, j--)

if (board[i][j])

return false;

return true;

// A recursive utility function to solve N

// Queen problem

bool solveNQUtil(int board[N][N], int col)

int i;

// Base case: If all queens are placed

// then return true

if (col >= N)

return true;

// Consider this column and try placing

// this queen in all rows one by one

for (i = 0; i < N; i++) {

// Check if the queen can be placed on

// board[i][col]

if (isSafe(board, i, col)) {

// Place this queen in board[i][col]

board[i][col] = 1;

// Recur to place rest of the queens

if (solveNQUtil(board, col + 1))

return true;
board[i][col] = 0; // BACKTRACK

return false;

bool solveNQ()

int board[N][N] = { { 0, 0, 0, 0 },

{ 0, 0, 0, 0 },

{ 0, 0, 0, 0 },

{ 0, 0, 0, 0 } };

if (solveNQUtil(board, 0) == false) {

printf("Solution does not exist");

return false;

printSolution(board);

return true;

// Driver program to test above function

int main()

solveNQ();

return 0;

}
OUTPUT:

11. Use Backtracking strategy to solve 0/1 Knapsack problem.

SOURCE CODE(USING C++):

// C++ program to solve knapsack problem using

#include <bits/stdc++.h>

using namespace std;

// Structure for Item which store weight and corresponding

// value of Item

struct Item

float weight;

int value;

};

struct Node

int level, profit, bound;

float weight;

};

bool cmp(Item a, Item b)

double r1 = (double)a.value / a.weight;

double r2 = (double)b.value / b.weight;

return r1 > r2;


}

int bound(Node u, int n, int W, Item arr[])

// if weight overcomes the knapsack capacity, return

// 0 as expected bound

if (u.weight >= W)

return 0;

// initialize bound on profit by current profit

int profit_bound = u.profit;

// start including items from index 1 more to current

// item index

int j = u.level + 1;

int totweight = u.weight;

// checking index condition and knapsack capacity

// condition

while ((j < n) && (totweight + arr[j].weight <= W))

totweight += arr[j].weight;

profit_bound += arr[j].value;

j++;

// If k is not n, include last item partially for

// upper bound on profit

if (j < n)

profit_bound += (W - totweight) * arr[j].value /

arr[j].weight;

return profit_bound;

// Returns maximum profit we can get with capacity W

int knapsack(int W, Item arr[], int n)

{
// sorting Item on basis of value per unit

// weight.

sort(arr, arr + n, cmp);

// make a queue for traversing the node

queue<Node> Q;

Node u, v;

// dummy node at starting

u.level = -1;

u.profit = u.weight = 0;

Q.push(u);

// One by one extract an item from decision tree

// compute profit of all children of extracted item

// and keep saving maxProfit

int maxProfit = 0;

while (!Q.empty())

// Dequeue a node

u = Q.front();

Q.pop();

// If it is starting node, assign level 0

if (u.level == -1)

v.level = 0;

// If there is nothing on next level

if (u.level == n-1)

continue;

// Else if not last node, then increment level,

// and compute profit of children nodes.


v.level = u.level + 1;

// Taking current level's item add current

// level's weight and value to node u's

// weight and value

v.weight = u.weight + arr[v.level].weight;

v.profit = u.profit + arr[v.level].value;

// If cumulated weight is less than W and

// profit is greater than previous profit,

// update maxprofit

if (v.weight <= W && v.profit > maxProfit)

maxProfit = v.profit;

// Get the upper bound on profit to decide

// whether to add v to Q or not.

v.bound = bound(v, n, W, arr);

// If bound value is greater than profit,

// then only push into queue for further

// consideration

if (v.bound > maxProfit)

Q.push(v);

// Do the same thing, but Without taking

// the item in knapsack

v.weight = u.weight;

v.profit = u.profit;

v.bound = bound(v, n, W, arr);

if (v.bound > maxProfit)

Q.push(v);

return maxProfit;
}

// driver program to test above function

int main()

int W = 10; // Weight of knapsack

Item arr[] = {{2, 40}, {3.14, 50}, {1.98, 100},

{5, 95}, {3, 30}};

int n = sizeof(arr) / sizeof(arr[0]);

cout << "Maximum possible profit = << knapsack(W, arr, n);

return 0;

OUTPUT:

12. Implement Travelling Sales Person problem using Branch and Bound approach.

SOURCE CODE(using C++):

// C++ program to solve Traveling Salesman Problem

// using Branch and Bound.

#include <bits/stdc++.h>

using namespace std;

const int N = 4;

// final_path[] stores the final solution ie, the

// path of the salesman.

int final_path[N+1];

// visited[] keeps track of the already visited nodes

// in a particular path

bool visited[N];
// Stores the final minimum weight of shortest tour.

int final_res = INT_MAX;

// Function to copy temporary solution to

// the final solution

void copyToFinal(int curr_path[])

for (int i=0; i<N; i++)

final_path[i] = curr_path[i];

final_path[N] = curr_path[0];

// Function to find the minimum edge cost

// having an end at the vertex i

int firstMin(int adj[N][N], int i)

int min = INT_MAX;

for (int k=0; k<N; k++)

if (adj[i][k]<min && i != k)

min = adj[i][k];

return min;

int secondMin(int adj[N][N], int i)

int first = INT_MAX, second = INT_MAX;

for (int j=0; j<N; j++)

if (i == j)

continue;

if (adj[i][j] <= first)

second = first;

first = adj[i][j];
}

else if (adj[i][j] <= second &&

adj[i][j] != first)

second = adj[i][j];

return second;

void TSPRec(int adj[N][N], int curr_bound, int curr_weight,

int level, int curr_path[])

if (level==N)

// check if there is an edge from last vertex in

// path back to the first vertex

if (adj[curr_path[level-1]][curr_path[0]] != 0)

// curr_res has the total weight of the

// solution we got

int curr_res = curr_weight +

adj[curr_path[level-1]][curr_path[0]];

// Update final result and final path if

// current result is better.

if (curr_res < final_res)

copyToFinal(curr_path);

final_res = curr_res;

return;

for (int i=0; i<N; i++)

{
if (adj[curr_path[level-1]][i] != 0 &&

visited[i] == false)

int temp = curr_bound;

curr_weight += adj[curr_path[level-1]][i];

// different computation of curr_bound for

// level 2 from the other levels

if (level==1)

curr_bound -= ((firstMin(adj, curr_path[level-1]) +

firstMin(adj, i))/2);

else

curr_bound -= ((secondMin(adj, curr_path[level-1]) +

firstMin(adj, i))/2);

if (curr_bound + curr_weight < final_res)

curr_path[level] = i;

visited[i] = true;

// call TSPRec for the next level

TSPRec(adj, curr_bound, curr_weight, level+1,

curr_path);

curr_weight -= adj[curr_path[level-1]][i];

curr_bound = temp;

// Also reset the visited array

memset(visited, false, sizeof(visited));

for (int j=0; j<=level-1; j++)

visited[curr_path[j]] = true;

}
// This function sets up final_path[]

void TSP(int adj[N][N])

int curr_path[N+1];

int curr_bound = 0;

memset(curr_path, -1, sizeof(curr_path));

memset(visited, 0, sizeof(curr_path));

// Compute initial bound

for (int i=0; i<N; i++)

curr_bound += (firstMin(adj, i) +

secondMin(adj, i));

// Rounding off the lower bound to an integer

curr_bound = (curr_bound&1)? curr_bound/2 + 1 :

curr_bound/2;

visited[0] = true;

curr_path[0] = 0;

TSPRec(adj, curr_bound, 0, 1, curr_path);

// Driver code

int main()

//Adjacency matrix for the given graph

int adj[N][N] = { {0, 10, 15, 20},

{10, 0, 35, 25},

{15, 35, 0, 30},

{20, 25, 30, 0}

};

TSP(adj);

printf("Minimum cost : %d\n", final_res);

printf("Path Taken : ");

for (int i=0; i<=N; i++)

printf("%d ", final_path[i]);


return 0;

OUTPUT:

Minimum cost : 80

Path Taken : 0 1 3 2 0

You might also like