Lab Manual
Lab Manual
Aim:
To implement the basic operations of a Stack Abstract Data Type (ADT) using an array in C.
The operations include:
1. Insert (push)
2. Delete (pop)
3. Display
Algorithm:
1. Insert (Push):
Check if the stack is full.
If the stack is full, print an overflow message.
If the stack is not full:
o Increment the top index.
o Insert the new element at the position pointed by top.
2. Delete (Pop):
Check if the stack is empty.
If the stack is empty, print an underflow message.
If the stack is not empty:
o Retrieve the element at the position pointed by top.
o Decrement the top index.
3. Display:
Check if the stack is empty.
If the stack is empty, print a message indicating that the stack is empty.
If the stack is not empty:
o Traverse from the top index to the 0 index and print each element.
Program:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
typedef struct {
int arr[MAX];
int top;
} Stack;
void initializeStack(Stack *s) {
s->top = -1;
}
int isFull(Stack *s) {
return s->top == MAX - 1;
}
int isEmpty(Stack *s) {
return s->top == -1;
}
int main() {
Stack s;
initializeStack(&s);
int choice, value;
while (1) {
printf("\nStack Operations:\n");
printf("1. Insert (Push)\n");
printf("2. Delete (Pop)\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to push: ");
scanf("%d", &value);
push(&s, value);
break;
case 2:
pop(&s);
break;
case 3:
display(&s);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:1 (b)
Array implementation of Queue
Date:
Aim:
To implement the basic operations of a Queue Abstract Data Type (ADT) using an array in C.
The operations include:
1. Insert (enqueue)
2. Delete (dequeue)
3. Display
Algorithm:
1. Insert (Enqueue):
Check if the queue is full.
If the queue is full, print an overflow message.
If the queue is not full:
o Increment the rear index.
o Insert the new element at the position pointed by rear.
2. Delete (Dequeue):
Check if the queue is empty.
If the queue is empty, print an underflow message.
If the queue is not empty:
o Retrieve the element at the position pointed by front.
o Increment the front index.
o If the front index surpasses the rear index, reset both front and rear to -1.
3. Display:
Program :
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
typedef struct {
int arr[MAX];
int front;
int rear;
} Queue;
int main() {
Queue q;
initializeQueue(&q);
int choice, value;
while (1) {
printf("\nQueue Operations:\n");
printf("1. Insert (Enqueue)\n");
printf("2. Delete (Dequeue)\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to enqueue: ");
scanf("%d", &value);
enqueue(&q, value);
break;
case 2:
dequeue(&q);
break;
case 3:
display(&q);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:1 (c)
Array implementation of Circular Queue
Date:
Aim:
To implement the basic operations of a Circular Queue Abstract Data Type (ADT) using an array
in C. The operations include:
1. Insert (enqueue)
2. Delete (dequeue)
Algorithm:
1. Insert (Enqueue):
Check if the queue is full.
If the queue is full, print an overflow message.
If the queue is not full:
o Increment the rear index in a circular manner.
o Insert the new element at the position pointed by rear.
2. Delete (Dequeue):
Check if the queue is empty.
If the queue is empty, print an underflow message.
If the queue is not empty:
o Retrieve the element at the position pointed by front.
o Increment the front index in a circular manner.
o If after deletion, the queue becomes empty, reset front and rear to -1.
Program:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
typedef struct {
int arr[MAX];
int front;
int rear;
} CircularQueue;
void initializeQueue(CircularQueue *q) {
q->front = -1;
q->rear = -1;
}
int isFull(CircularQueue *q) {
return (q->front == (q->rear + 1) % MAX);
}
int main() {
CircularQueue q;
initializeQueue(&q);
int choice, value;
while (1) {
printf("\nCircular Queue Operations:\n");
printf("1. Insert (Enqueue)\n");
printf("2. Delete (Dequeue)\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to enqueue: ");
scanf("%d", &value);
enqueue(&q, value);
break;
case 2:
dequeue(&q);
break;
case 3:
display(&q);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:2
Singly Linked List
Date:
Aim:
To implement the following operations on a singly linked list of integers using functions in C:
a) Create a singly linked list. b) Delete a given integer from the list. c) Display the contents of
the list after deletion.
Algorithm:
a) Create a singly linked list:
1. Initialize the head of the list as NULL.
2. Create a new node.
3. Assign the integer value to the new node.
4. Set the next pointer of the new node to NULL.
5. If the list is empty, set the head to the new node.
6. If the list is not empty, traverse to the end of the list and add the new node.
b) Delete a given integer from the list:
1. Initialize two pointers, prev and current, starting from the head of the list.
2. Traverse the list until the node with the given integer is found or the end of the list is
reached.
3. If the node is found:
o If it is the head node, update the head to the next node.
o Otherwise, update the next pointer of the previous node to skip the node to be
deleted.
4. Free the memory of the node to be deleted.
5. If the node is not found, print an appropriate message.
c) Display the contents of the list:
1. Initialize a pointer to the head of the list.
2. Traverse the list until the end is reached.
3. Print the data of each node.
Program:
#include <stdio.h>
#include <stdlib.h>
int main() {
Node *head = NULL;
int choice, value;
while (1) {
printf("\nLinked List Operations:\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to insert: ");
scanf("%d", &value);
insertNode(&head, value);
break;
case 2:
printf("Enter the value to delete: ");
scanf("%d", &value);
deleteNode(&head, value);
break;
case 3:
displayList(head);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:3 (a)
Stack using Linked List
Date:
Aim:
To implement the basic operations of a Stack Abstract Data Type (ADT) using a linked list in C.
The operations include:
1. Push (insert an element onto the stack)
2. Pop (remove an element from the stack)
3. Display (display all elements of the stack)
Algorithm:
1. Push:
Create a new node.
Assign the data to the new node.
Set the next pointer of the new node to the current top of the stack.
Update the top of the stack to the new node.
2. Pop:
Check if the stack is empty.
If the stack is empty, print an underflow message.
If the stack is not empty:
o Retrieve the data from the top node.
o Update the top to the next node.
o Free the memory of the old top node.
3. Display:
Initialize a pointer to the top of the stack.
Traverse the stack until the end is reached.
Print the data of each node.
Program:
#include <stdio.h>
#include <stdlib.h>
int main() {
Node *top = NULL;
int choice, value;
while (1) {
printf("\nStack Operations:\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to push: ");
scanf("%d", &value);
push(&top, value);
break;
case 2:
pop(&top);
break;
case 3:
display(top);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:3 (b)
Queue using Linked List
Date:
Aim:
To implement the basic operations of a linear queue Abstract Data Type (ADT) using a linked
list in C. The operations include:
1. Enqueue (insert an element into the queue)
2. Dequeue (remove an element from the queue)
3. Display (display all elements of the queue)
Algorithm:
1. Enqueue:
Create a new node.
Assign the data to the new node.
Set the next pointer of the new node to NULL.
If the queue is empty (both front and rear are NULL), set both front and rear to the new
node.
If the queue is not empty, set the next pointer of the rear node to the new node and
update the rear to the new node.
2. Dequeue:
Check if the queue is empty.
If the queue is empty, print an underflow message.
If the queue is not empty:
o Retrieve the data from the front node.
o Update the front to the next node.
o If the front becomes NULL, also set rear to NULL (queue is now empty).
o Free the memory of the old front node.
3. Display:
Initialize a pointer to the front of the queue.
Traverse the queue until the end is reached.
Print the data of each node.
Program:
#include <stdio.h>
#include <stdlib.h>
int main() {
Node *front = NULL;
Node *rear = NULL;
int choice, value;
while (1) {
printf("\nQueue Operations:\n");
printf("1. Enqueue\n");
printf("2. Dequeue\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the value to enqueue: ");
scanf("%d", &value);
enqueue(&front, &rear, value);
break;
case 2:
dequeue(&front, &rear);
break;
case 3:
display(front);
break;
case 4:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:4
Polynomial Manipulation using Linked List
Date:
Aim:
To implement polynomial addition and multiplication using linked lists in C. Each polynomial is
represented as a linked list where each node contains the coefficient and exponent of a term.
Algorithm:
1. Polynomial Addition:
1. Initialize pointers for both polynomials and a result polynomial.
2. Traverse both polynomials simultaneously.
3. Compare the exponents of the current terms.
o If the exponents are equal, add the coefficients and create a new node in the result
polynomial.
o If the exponent of the first polynomial is greater, add the term from the first
polynomial to the result.
o If the exponent of the second polynomial is greater, add the term from the second
polynomial to the result.
4. Continue until both polynomials are fully traversed.
5. Add any remaining terms from either polynomial to the result.
2. Polynomial Multiplication:
1. Initialize pointers for both polynomials and a result polynomial.
2. Traverse the first polynomial.
3. For each term in the first polynomial, traverse the second polynomial.
4. Multiply the current terms from both polynomials.
5. Add the resulting term to the appropriate position in the result polynomial.
6. Continue until all terms from both polynomials are multiplied.
Program:
#include <stdio.h>
#include <stdlib.h>
// Definition of the Node structure
typedef struct Node {
int coeff;
int exp;
struct Node *next;
} Node;
// Function to insert a node into the polynomial list in descending order of exponents
void insertNode(Node **head, int coeff, int exp) {
Node *newNode = createNode(coeff, exp);
if (*head == NULL || (*head)->exp < exp) {
newNode->next = *head;
*head = newNode;
} else {
Node *temp = *head;
while (temp->next != NULL && temp->next->exp > exp) {
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
}
int main() {
Node *poly1 = NULL, *poly2 = NULL, *result = NULL;
int choice, coeff, exp;
while (1) {
printf("\nPolynomial Operations:\n");
printf("1. Insert term in Polynomial 1\n");
printf("2. Insert term in Polynomial 2\n");
printf("3. Display Polynomial 1\n");
printf("4. Display Polynomial 2\n");
printf("5. Add Polynomials\n");
printf("6. Multiply Polynomials\n");
printf("7. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter coefficient and exponent: ");
scanf("%d %d", &coeff, &exp);
insertNode(&poly1, coeff, exp);
break;
case 2:
printf("Enter coefficient and exponent: ");
scanf("%d %d", &coeff, &exp);
insertNode(&poly2, coeff, exp);
break;
case 3:
printf("Polynomial 1: ");
displayPolynomial(poly1);
break;
case 4:
printf("Polynomial 2: ");
displayPolynomial(poly2);
break;
case 5:
result = addPolynomials(poly1, poly2);
printf("Result of addition: ");
displayPolynomial(result);
break;
case 6:
result = multiplyPolynomials(poly1, poly2);
printf("Result of multiplication: ");
displayPolynomial(result);
break;
case 7:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:5 (a)
Evaluating Postfix Expression
Date:
Aim:
Algorithm:
2. Traverse the postfix expression from left to right for each character:
3. The final result will be the only element left in the stack.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
// If the character is an operator, pop two elements from stack, apply the operator and push
the result back
else {
int val1 = pop(stack);
int val2 = pop(stack);
switch (exp[i]) {
case '+': push(stack, val2 + val1); break;
case '-': push(stack, val2 - val1); break;
case '*': push(stack, val2 * val1); break;
case '/': push(stack, val2 / val1); break;
}
}
}
return pop(stack);
}
int main() {
char exp[] = "100 200 + 2 / 5 * 7 +"; // Example expression
printf("Postfix expression: %s\n", exp);
printf("Result: %d\n", evaluatePostfix(exp));
return 0;
}
Output:
Inference:
Result:
Ex:No:5 (b)
Infix to Postfix Conversion
Date:
Aim:
To implement a program that converts infix expressions to postfix expressions using a stack in C.
Algorithm:
1. Initialize an empty stack and an empty postfix expression string.
2. Traverse the infix expression from left to right for each character:
If the character is an operand, append it to the postfix expression.
If the character is '(', push it onto the stack.
If the character is ')', pop from the stack and append to the postfix expression until '(' is
encountered.
If the character is an operator:
o While the stack is not empty and the precedence of the operator on the stack is
greater than or equal to the precedence of the current operator, pop from the stack
and append to the postfix expression.
o Push the current operator onto the stack.
3. Pop all remaining operators from the stack and append to the postfix expression.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
result[k] = '\0';
}
int main() {
char infix1[] = "A+B*C+D";
char infix2[] = "(A+B)*(C+D)";
char infix3[] = "A*B+C*D";
char infix4[] = "A+B+C+D";
char postfix[100];
infixToPostfix(infix1, postfix);
printf("Infix: %s\nPostfix: %s\n\n", infix1, postfix);
infixToPostfix(infix2, postfix);
printf("Infix: %s\nPostfix: %s\n\n", infix2, postfix);
infixToPostfix(infix3, postfix);
printf("Infix: %s\nPostfix: %s\n\n", infix3, postfix);
infixToPostfix(infix4, postfix);
printf("Infix: %s\nPostfix: %s\n\n", infix4, postfix);
return 0;
}
Output:
Inference:
Result:
Ex:No:6
Binary Search Tree
Date:
Aim:
To implement a Binary Search Tree (BST) in C with operations to create a tree, insert nodes,
find the minimum value, and find the maximum value.
Algorithm:
Binary Search Tree Operations:
1. Create:
o Initialize an empty tree (i.e., set the root to NULL).
2. Insert:
o Start at the root of the tree.
o If the tree is empty, insert the new node as the root.
o Otherwise, recursively find the correct position for the new node:
If the value to be inserted is less than the current node's value, move to the
left child.
If the value to be inserted is greater than the current node's value, move to
the right child.
o Insert the new node when the correct position is found.
3. Findmin:
o Traverse the left subtree of the tree starting from the root.
o Continue traversing left until the leftmost node is reached. This node contains the
minimum value.
4. Findmax:
o Traverse the right subtree of the tree starting from the root.
o Continue traversing right until the rightmost node is reached. This node contains
the maximum value.
Program:
#include <stdio.h>
#include <stdlib.h>
return 0;
}
Output:
Inference:
Result:
Ex:No:7
AVL Tree
Date:
Aim:
To implement an AVL tree in C and perform operations including insertion of nodes while
maintaining balance, rotation to keep the tree balanced, and traversal to display the tree.
Algorithm:
1. Insertion:
1. Perform a standard BST insertion.
2. Update the height of each node.
3. Calculate the balance factor for each node.
4. Perform rotations (if needed) to ensure the tree remains balanced.
2. Rotations:
Right Rotation: Used when a node's left subtree is taller.
Left Rotation: Used when a node's right subtree is taller.
Left-Right Rotation: A combination of left rotation on the left child followed by right
rotation on the node.
Right-Left Rotation: A combination of right rotation on the right child followed by left
rotation on the node.
3. Preorder Traversal:
Visit the root node.
Traverse the left subtree.
Traverse the right subtree.
Program:
#include <stdio.h>
#include <stdlib.h>
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));
x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));
y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));
// 3. Get the balance factor of this ancestor node to check whether this node became
unbalanced
int balance = getBalance(node);
return 0;
}
Output:
Inference:
Result:
Ex:No:8
Priority Queue
Date:
Aim:
To implement a binary heap using a priority queue in C. This will involve operations such as
insertion, deletion of the minimum (or maximum), and displaying the elements of the heap.
Algorithm:
1. Insert Operation:
1. Add the new element at the end of the heap (maintaining the complete tree property).
2. Heapify-up: Compare the newly added element with its parent and swap if necessary to
maintain the heap property.
2. Delete Operation (Removing the Root):
1. Replace the root of the heap with the last element in the heap.
2. Remove the last element.
3. Heapify-down: Compare the root with its children and swap with the smaller child (for a
min-heap) to restore the heap property.
3. Display the Heap:
1. Traverse the heap array and print the elements.
Program:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef struct {
int size;
int data[MAX_SIZE];
} BinaryHeap;
if (smallest != index) {
swap(&heap->data[index], &heap->data[smallest]);
heapifyDown(heap, smallest);
}
}
heap->data[heap->size] = value;
heap->size++;
heapifyUp(heap, heap->size - 1);
}
return root;
}
insert(&heap, 10);
insert(&heap, 20);
insert(&heap, 5);
insert(&heap, 6);
insert(&heap, 1);
insert(&heap, 8);
insert(&heap, 9);
printf("Heap elements:\n");
displayHeap(&heap);
return 0;
}
Output:
Inference:
Result:
Ex:No:9
Dijkstra’s algorithm
Date:
Aim:
To implement Dijkstra's algorithm in C to find the shortest path from a source node to all other
nodes in a weighted graph.
Algorithm:
1. Initialize:
1. Distances Array: Set the distance to the source node as 0 and all other nodes as infinity.
2. Visited Array: Keep track of visited nodes to avoid processing the same node more than
once.
2. Algorithm Execution:
1. Find Minimum Distance Node: Choose the node with the smallest distance from the
source that has not been visited.
2. Update Distances: For each neighbor of the selected node, update the distance if a
shorter path is found.
3. Mark as Visited: Mark the current node as visited.
3. Repeat:
Continue the process until all nodes are visited or the smallest distance among unvisited
nodes is infinity (indicating the remaining nodes are not reachable).
Program:
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
// Update the distance value of the adjacent vertices of the picked vertex
for (int v = 0; v < V; 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];
}
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:10
Prim’s algorithm
Date:
Aim:
To implement Prim's Algorithm in C to find the Minimum Spanning Tree of a connected,
undirected graph.
Algorithm:
1. Initialize:
1. Key Array: Store the minimum weight edge connecting each vertex to the growing
MST.
2. Parent Array: Store the parent of each vertex in the MST.
3. Included Array: Keep track of vertices included in the MST.
2. Algorithm Execution:
1. Start from the Source Vertex: Initialize the key of the source vertex to 0 and the rest to
infinity.
2. Select Minimum Key Vertex: Choose the vertex with the minimum key value that is not
yet included in the MST.
3. Update Key Values: For every adjacent vertex of the chosen vertex, update its key value
if a smaller weight edge is found.
4. Repeat: Continue until all vertices are included in the MST.
Program:
#include <stdio.h>
#include <limits.h>
#define V 5 // Number of vertices in the graph
// Function to find the vertex with the minimum key value
int minKey(int key[], bool mstSet[]) {
int min = INT_MAX, min_index;
// Update key value and parent index of the adjacent vertices of the picked vertex
for (int v = 0; v < V; v++) {
// Update key[v] if and only if graph[u][v] is smaller than key[v] and v is not in mstSet
if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v]) {
key[v] = graph[u][v];
parent[v] = u;
}
}
}
return 0;
}
Output:
Inference:
Result:
Ex:No:11(a)
Linear Search
Date:
Aim:
To implement the Linear Search algorithm in C, which searches for a specified value in an array
by checking each element sequentially until the desired value is found or the end of the array is
reached.
Algorithm:
Linear Search:
1. Start: Begin at the first element of the array.
2. Search: Compare the target value with the current element of the array.
3. Check:
o If the current element matches the target value, return the index of the element.
o If the current element does not match the target value, move to the next element.
4. Continue: Repeat the process until the target value is found or the end of the array is
reached.
5. End: If the end of the array is reached without finding the target value, return -1
indicating that the value is not present in the array.
Program:
#include <stdio.h>
// Function to perform linear search
int linearSearch(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
return i; // Target found, return index
}
}
return -1; // Target not found
}
if (result != -1) {
printf("Element found at index %d\n", result);
} else {
printf("Element not found in the array\n");
}
return 0;
}
Output:
Inference:
Result:
Ex:No:11(b)
Binary Search
Date:
Aim:
To implement the Binary Search algorithm in C, which efficiently searches for a target value in a
sorted array by repeatedly dividing the search interval in half.
Algorithm:
Binary Search:
1. Initialize:
o Set low to the index of the first element ( 0).
o Set high to the index of the last element ( size - 1).
2. Search:
o While low is less than or equal to high:
Calculate the middle index: mid = low + (high - low) / 2.
Compare the target value with the element at the middle index:
If the target value is equal to the middle element, return the mid
index.
If the target value is less than the middle element, adjust high to
mid - 1 (search the left half).
If the target value is greater than the middle element, adjust low to
mid + 1 (search the right half).
3. End:
o If the target value is not found, return -1 indicating that the value is not present in
the array.
Program:
#include <stdio.h>
// Function to perform binary search
int binarySearch(int arr[], int size, int target) {
int low = 0;
int high = size - 1;
if (result != -1) {
printf("Element found at index %d\n", result);
} else {
printf("Element not found in the array\n");
}
return 0;
}
Output:
Inference:
Result:
Ex:No:12(a)
Insertion Sort
Date:
Aim:
To implement the Insertion Sort algorithm in C to arrange a list of integers in ascending order.
Algorithm:
Insertion Sort:
1. Initialization:
o Start from the second element (index 1) since a single element (index 0) is already
considered sorted.
2. Insertion:
o For each element (key), compare it with the elements in the sorted portion of the
array (i.e., elements before the current element).
o Shift elements of the sorted portion that are greater than the key to one position
ahead.
o Insert the key into its correct position.
3. Repeat:
o Continue this process for all elements in the array.
Program:
#include <stdio.h>
// Function to perform insertion sort
void insertionSort(int arr[], int size) {
int key, j;
for (int i = 1; i < size; i++) {
key = arr[i];
j = i - 1;
// Shift elements of the sorted portion that are greater than key
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
printf("Original array:\n");
printArray(arr, size);
insertionSort(arr, size);
return 0;
}
Output:
Inference:
Result:
Ex:No:12(b)
Selection Sort
Date:
Aim:
To implement the Selection Sort algorithm in C to arrange a list of integers in ascending order.
Algorithm:
Selection Sort:
1. Initialization:
o Start with the first element of the array.
2. Selection:
o For each position in the array, find the smallest element from the current position
to the end of the array.
o Swap the smallest element found with the element at the current position.
3. Repeat:
o Move to the next position and repeat the process until the entire array is sorted.
Program:
#include <stdio.h>
// Function to perform selection sort
void selectionSort(int arr[], int size) {
int i, j, minIndex, temp;
// Find the index of the minimum element in the remaining unsorted portion
for (j = i + 1; j < size; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
printf("Original array:\n");
printArray(arr, size);
selectionSort(arr, size);
return 0;
}
Output:
Inference:
Result:
Ex:No:13
Merge Sort
Date:
Aim:
To implement the Merge Sort algorithm in C, which is a divide-and-conquer algorithm used to
sort an array in ascending order by recursively dividing the array into smaller subarrays, sorting
those subarrays, and then merging them back together.
Algorithm:
Merge Sort:
1. Divide:
o If the array has more than one element, divide the array into two halves.
o Recursively apply Merge Sort to both halves.
2. Conquer:
o Merge the two halves together in sorted order.
o To merge, use two pointers to traverse the two halves and combine them into a
single sorted array.
3. Combine:
o Combine the sorted halves to form a fully sorted array.
Program:
#include <stdio.h>
#include <stdlib.h>
// Function to merge two halves of an array
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
printf("Original array:\n");
printArray(arr, size);
return 0;
}
Output:
Inference:
Result:
Ex:No:14(a)
Open Addressing-Linear Probing
Date:
Aim:
To implement Linear Probing Hashing in C, a technique used to resolve collisions in a hash
table. Linear probing involves finding the next available slot in a sequential manner when a
collision occurs during insertion.
Algorithm:
1. Initialize:
o Create a hash table with a fixed size (e.g., an array of pointers).
o Initialize all slots to NULL (or a sentinel value indicating empty).
2. Hash Function:
o Use a hash function to determine the initial position in the hash table for a given
key. For example, use the modulus operator to map the key to an index in the
array.
3. Insertion:
o Compute the hash value for the key.
o If the computed position is occupied, probe sequentially (i.e., check the next slot)
until an empty slot is found.
4. Search:
o Compute the hash value for the key.
o Check the slot at the computed position. If the key is not found, probe
sequentially until either the key is found or an empty slot is encountered.
5. Deletion:
o Compute the hash value for the key.
o Check the slot at the computed position. If the key is found, mark the slot as
deleted (e.g., using a sentinel value). Probe sequentially if necessary.
Program:
#include <stdio.h>
#include <stdlib.h>
#define TABLE_SIZE 10
#define EMPTY -1
#define DELETED -2
// Delete an element
delete(hashTable, 30);
printf("Hash Table after deletion of key 30:\n");
printHashTable(hashTable);
return 0;
}
Output:
Inference:
Result:
Ex:No:14(b)
Open Addressing-Quadratic Probing
Date:
Aim:
To implement Quadratic Probing in C for collision resolution in a hash table. Quadratic probing
is a technique used to find an open slot in a hash table when a collision occurs, by probing the
table using a quadratic function.
Algorithm:
1. Initialize:
o Create a hash table with a fixed size (e.g., an array).
o Initialize all slots to NULL or a sentinel value indicating that they are empty.
2. Hash Function:
o Use a hash function to compute the initial position in the hash table for a given
key. Typically, this is done using the modulus operator.
3. Insertion:
o Compute the initial position using the hash function.
o If the slot is occupied, use quadratic probing to find the next available slot:
Try slots at intervals defined by i2i^2i2, where iii is the probe number
(i.e., i=1,2,3,…i = 1, 2, 3, \ldotsi=1,2,3,…).
The slot to be checked is computed as (index+i2)%TABLE_SIZE(index +
i^2) \% TABLE\_SIZE(index+i2)%TABLE_SIZE.
4. Search:
o Compute the initial position using the hash function.
o Check the slot at the computed position. If the key is not found, use quadratic
probing to continue searching:
Check slots at intervals defined by i2i^2i2 until either the key is found or
an empty slot is encountered.
5. Deletion:
o Compute the initial position using the hash function.
o Use quadratic probing to find the key in the hash table.
o Mark the slot as deleted if the key is found, using a sentinel value for deletion.
Program:
#include <stdio.h>
#include <stdlib.h>
#define TABLE_SIZE 10
#define EMPTY -1
#define DELETED -2
// Function to insert a key into the hash table using quadratic probing
void insert(int hashTable[], int key) {
int index = hashFunction(key);
int i = 0;
// Function to search for a key in the hash table using quadratic probing
int search(int hashTable[], int key) {
int index = hashFunction(key);
int i = 0;
// Function to delete a key from the hash table using quadratic probing
void delete(int hashTable[], int key) {
int index = search(hashTable, key);
if (index != -1) {
hashTable[index] = DELETED;
} else {
printf("Key not found\n");
}
}
// Delete an element
delete(hashTable, 30);
printf("Hash Table after deletion of key 30:\n");
printHashTable(hashTable);
return 0;
}
Output:
Inference:
Result:
Ex:No:15
Radix Sort
Date:
Aim:
To implement the Radix Sort algorithm in C, which is a non-comparative integer sorting
algorithm that sorts numbers by processing individual digits. Radix Sort works by distributing
the numbers into buckets based on each digit and then collecting the numbers back into a sorted
sequence, repeating this process for each digit place.
Algorithm:
Radix Sort:
1. Find the Maximum Number:
o Determine the maximum number in the array to find the number of digits in the
largest number.
2. Sort by Each Digit:
o For each digit place (starting from the least significant digit to the most significant
digit):
1. Use Counting Sort:
Create buckets for each digit (0-9).
Distribute the numbers into these buckets based on the current digit
place.
Collect the numbers back into the array from the buckets.
3. Repeat:
o Continue the process for each digit place until all digit places have been
processed.
Program:
#include <stdio.h>
#include <stdlib.h>
free(output);
}
printf("Original array:\n");
printArray(arr, size);
radixSort(arr, size);
printf("Sorted array:\n");
printArray(arr, size);
return 0;
}
Output:
Inference:
Result:
Ex:No:16
Shell Sort
Date:
Aim:
To implement the Shell Sort algorithm in C. Shell Sort is an in-place comparison-based sorting
algorithm that generalizes insertion sort to allow the exchange of items that are far apart. It
improves on insertion sort by sorting elements at specific intervals, which reduces the amount of
shifting needed and helps in sorting large arrays efficiently.
Algorithm:
Shell Sort:
1. Initialize:
o Start with an initial gap size. The gap size reduces in each iteration until it
becomes zero.
2. Sort with Gap:
o For each gap size, perform a modified insertion sort where elements that are gap
positions apart are compared and sorted.
3. Reduce Gap:
o After each pass with a given gap, reduce the gap size (typically by a factor of 2 or
using a specific sequence) and repeat the process.
4. Termination:
o Continue the process until the gap size is reduced to zero. At this point, the array
should be sorted.
Program:
#include <stdio.h>
printf("Original array:\n");
printArray(arr, size);
shellSort(arr, size);
printf("Sorted array:\n");
printArray(arr, size);
return 0;
}
Output:
Inference:
Result: