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

Lab Manual

The document outlines the implementation of various data structures in C, including Stack, Queue, Circular Queue, and Singly Linked List, detailing their basic operations such as insert, delete, and display. Each section provides an algorithm and corresponding C code for the operations, ensuring clarity in how to manage these data structures. The document serves as a comprehensive guide for understanding and implementing these fundamental data structures in programming.

Uploaded by

Akshaya R
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Lab Manual

The document outlines the implementation of various data structures in C, including Stack, Queue, Circular Queue, and Singly Linked List, detailing their basic operations such as insert, delete, and display. Each section provides an algorithm and corresponding C code for the operations, ensuring clarity in how to manage these data structures. The document serves as a comprehensive guide for understanding and implementing these fundamental data structures in programming.

Uploaded by

Akshaya R
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 77

Ex:No:1 (a)

Array implementation of Stack


Date:

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

void push(Stack *s, int value) {


if (isFull(s)) {
printf("Stack overflow\n");
return;
}
s->arr[++s->top] = value;
printf("%d pushed to stack\n", value);
}

void pop(Stack *s) {


if (isEmpty(s)) {
printf("Stack underflow\n");
return;
}
int poppedValue = s->arr[s->top--];
printf("%d popped from stack\n", poppedValue);
}

void display(Stack *s) {


if (isEmpty(s)) {
printf("Stack is empty\n");
return;
}
printf("Stack elements: ");
for (int i = s->top; i >= 0; i--) {
printf("%d ", s->arr[i]);
}
printf("\n");
}

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:

 Check if the queue is empty.


 If the queue is empty, print a message indicating that the queue is empty.
 If the queue is not empty:
o Traverse from the front index to the rear index and print each element.

Program :
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
typedef struct {
int arr[MAX];
int front;
int rear;
} Queue;

void initializeQueue(Queue *q) {


q->front = -1;
q->rear = -1;
}
int isFull(Queue *q) {
return q->rear == MAX - 1;
}
int isEmpty(Queue *q) {
return q->front == -1 || q->front > q->rear;
}

void enqueue(Queue *q, int value) {


if (isFull(q)) {
printf("Queue overflow\n");
return;
}
if (isEmpty(q)) {
q->front = 0;
}
q->arr[++q->rear] = value;
printf("%d enqueued to queue\n", value);
}

void dequeue(Queue *q) {


if (isEmpty(q)) {
printf("Queue underflow\n");
return;
}
int dequeuedValue = q->arr[q->front++];
printf("%d dequeued from queue\n", dequeuedValue);
if (q->front > q->rear) {
q->front = q->rear = -1;
}
}

void display(Queue *q) {


if (isEmpty(q)) {
printf("Queue is empty\n");
return;
}
printf("Queue elements: ");
for (int i = q->front; i <= q->rear; i++) {
printf("%d ", q->arr[i]);
}
printf("\n");
}

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 isEmpty(CircularQueue *q) {


return q->front == -1;
}

void enqueue(CircularQueue *q, int value) {


if (isFull(q)) {
printf("Queue overflow\n");
return;
}
if (isEmpty(q)) {
q->front = 0;
}
q->rear = (q->rear + 1) % MAX;
q->arr[q->rear] = value;
printf("%d enqueued to queue\n", value);
}

void dequeue(CircularQueue *q) {


if (isEmpty(q)) {
printf("Queue underflow\n");
return;
}
int dequeuedValue = q->arr[q->front];
printf("%d dequeued from queue\n", dequeuedValue);
if (q->front == q->rear) {
q->front = q->rear = -1;
} else {
q->front = (q->front + 1) % MAX;
}
}

void display(CircularQueue *q) {


if (isEmpty(q)) {
printf("Queue is empty\n");
return;
}
printf("Queue elements: ");
int i = q->front;
while (1) {
printf("%d ", q->arr[i]);
if (i == q->rear) {
break;
}
i = (i + 1) % MAX;
}
printf("\n");
}

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>

// Definition of the Node structure


typedef struct Node {
int data;
struct Node *next;
} Node;

// Function to create a new node


Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return NULL;
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}

// Function to insert a new node at the end of the list


void insertNode(Node **head, int data) {
Node *newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
} else {
Node *temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
printf("%d inserted into the list\n", data);
}

// Function to delete a node with a given integer from the list


void deleteNode(Node **head, int key) {
Node *temp = *head, *prev = NULL;

// If the head node itself holds the key to be deleted


if (temp != NULL && temp->data == key) {
*head = temp->next; // Changed head
free(temp); // Free old head
printf("%d deleted from the list\n", key);
return;
}

// Search for the key to be deleted


while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}

// If key was not present in the list


if (temp == NULL) {
printf("%d not found in the list\n", key);
return;
}

// Unlink the node from the list


prev->next = temp->next;
free(temp); // Free memory
printf("%d deleted from the list\n", key);
}

// Function to display the contents of the list


void displayList(Node *head) {
if (head == NULL) {
printf("The list is empty\n");
return;
}
Node *temp = head;
printf("List contents: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

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>

// Definition of the Node structure


typedef struct Node {
int data;
struct Node *next;
} Node;

// Function to create a new node


Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return NULL;
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}

// Function to push an element onto the stack


void push(Node **top, int data) {
Node *newNode = createNode(data);
if (!newNode) return;
newNode->next = *top;
*top = newNode;
printf("%d pushed to stack\n", data);
}

// Function to pop an element from the stack


void pop(Node **top) {
if (*top == NULL) {
printf("Stack underflow\n");
return;
}
Node *temp = *top;
*top = (*top)->next;
printf("%d popped from stack\n", temp->data);
free(temp);
}

// Function to display the contents of the stack


void display(Node *top) {
if (top == NULL) {
printf("Stack is empty\n");
return;
}
Node *temp = top;
printf("Stack elements: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

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>

// Definition of the Node structure


typedef struct Node {
int data;
struct Node *next;
} Node;

// Function to create a new node


Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return NULL;
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}

// Function to enqueue an element into the queue


void enqueue(Node **front, Node **rear, int data) {
Node *newNode = createNode(data);
if (!newNode) return;
if (*rear == NULL) {
*front = *rear = newNode;
} else {
(*rear)->next = newNode;
*rear = newNode;
}
printf("%d enqueued to queue\n", data);
}

// Function to dequeue an element from the queue


void dequeue(Node **front, Node **rear) {
if (*front == NULL) {
printf("Queue underflow\n");
return;
}
Node *temp = *front;
*front = (*front)->next;
if (*front == NULL) {
*rear = NULL;
}
printf("%d dequeued from queue\n", temp->data);
free(temp);
}

// Function to display the contents of the queue


void display(Node *front) {
if (front == NULL) {
printf("Queue is empty\n");
return;
}
Node *temp = front;
printf("Queue elements: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

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 create a new node


Node* createNode(int coeff, int exp) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return NULL;
}
newNode->coeff = coeff;
newNode->exp = exp;
newNode->next = NULL;
return newNode;
}

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

// Function to display the polynomial


void displayPolynomial(Node *head) {
if (head == NULL) {
printf("0\n");
return;
}
Node *temp = head;
while (temp != NULL) {
if (temp->coeff != 0) {
printf("%dx^%d", temp->coeff, temp->exp);
if (temp->next != NULL && temp->next->coeff > 0)
printf(" + ");
}
temp = temp->next;
}
printf("\n");
}

// Function to add two polynomials


Node* addPolynomials(Node *poly1, Node *poly2) {
Node *result = NULL;
while (poly1 != NULL && poly2 != NULL) {
if (poly1->exp > poly2->exp) {
insertNode(&result, poly1->coeff, poly1->exp);
poly1 = poly1->next;
} else if (poly1->exp < poly2->exp) {
insertNode(&result, poly2->coeff, poly2->exp);
poly2 = poly2->next;
} else {
insertNode(&result, poly1->coeff + poly2->coeff, poly1->exp);
poly1 = poly1->next;
poly2 = poly2->next;
}
}
while (poly1 != NULL) {
insertNode(&result, poly1->coeff, poly1->exp);
poly1 = poly1->next;
}
while (poly2 != NULL) {
insertNode(&result, poly2->coeff, poly2->exp);
poly2 = poly2->next;
}
return result;
}

// Function to multiply two polynomials


Node* multiplyPolynomials(Node *poly1, Node *poly2) {
Node *result = NULL;
Node *tempPoly2 = poly2;
while (poly1 != NULL) {
poly2 = tempPoly2;
while (poly2 != NULL) {
int coeff = poly1->coeff * poly2->coeff;
int exp = poly1->exp + poly2->exp;
insertNode(&result, coeff, exp);
poly2 = poly2->next;
}
poly1 = poly1->next;
}
return result;
}

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:

To implement a program that evaluates a postfix expression using a stack in C.

Algorithm:

1. Initialize an empty stack.

2. Traverse the postfix expression from left to right for each character:

 If the character is an operand, push it onto the stack.


 If the character is an operator, pop the top two elements from the stack, perform the
operation, and push the result back onto the stack.

3. The final result will be the only element left in the stack.

Program:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

// Definition of the Stack structure


typedef struct Stack {
int top;
unsigned capacity;
int* array;
} Stack;

// Function to create a stack of given capacity


Stack* createStack(unsigned capacity) {
Stack* stack = (Stack*)malloc(sizeof(Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (int*)malloc(stack->capacity * sizeof(int));
return stack;
}

// Function to check if the stack is empty


int isEmpty(Stack* stack) {
return stack->top == -1;
}

// Function to check if the stack is full


int isFull(Stack* stack) {
return stack->top == stack->capacity - 1;
}
// Function to push an item to the stack
void push(Stack* stack, int item) {
if (isFull(stack))
return;
stack->array[++stack->top] = item;
}

// Function to pop an item from the stack


int pop(Stack* stack) {
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top--];
}

// Function to evaluate a postfix expression


int evaluatePostfix(char* exp) {
// Create a stack of capacity equal to the length of the expression
Stack* stack = createStack(strlen(exp));
int i;

// Traverse the given postfix expression


for (i = 0; exp[i]; ++i) {
// If the character is a whitespace, skip it
if (exp[i] == ' ')
continue;

// If the character is a digit, push it to the stack


else if (isdigit(exp[i])) {
int num = 0;
// Extract full number
while (isdigit(exp[i])) {
num = num * 10 + (exp[i] - '0');
i++;
}
i--; // decrement to correct for the increment in the for loop
push(stack, num);
}

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

// Definition of the Stack structure


typedef struct Stack {
int top;
unsigned capacity;
int* array;
} Stack;

// Function to create a stack of given capacity


Stack* createStack(unsigned capacity) {
Stack* stack = (Stack*)malloc(sizeof(Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (int*)malloc(stack->capacity * sizeof(int));
return stack;
}

// Function to check if the stack is empty


int isEmpty(Stack* stack) {
return stack->top == -1;
}

// Function to check if the stack is full


int isFull(Stack* stack) {
return stack->top == stack->capacity - 1;
}

// Function to push an item to the stack


void push(Stack* stack, char item) {
if (isFull(stack))
return;
stack->array[++stack->top] = item;
}

// Function to pop an item from the stack


char pop(Stack* stack) {
if (isEmpty(stack))
return '$';
return stack->array[stack->top--];
}

// Function to get the precedence of operators


int precedence(char op) {
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
return 0;
}

// Function to convert infix to postfix


void infixToPostfix(char* exp, char* result) {
int i, k = 0;
Stack* stack = createStack(strlen(exp));
if (!stack)
return;

for (i = 0; exp[i]; i++) {


// If the character is an operand, add it to output
if (isalnum(exp[i])) {
result[k++] = exp[i];
}
// If the character is '(', push it to stack
else if (exp[i] == '(') {
push(stack, exp[i]);
}
// If the character is ')', pop and output from the stack until '(' is found
else if (exp[i] == ')') {
while (!isEmpty(stack) && stack->array[stack->top] != '(')
result[k++] = pop(stack);
if (!isEmpty(stack) && stack->array[stack->top] != '(')
return; // invalid expression
else
pop(stack);
}
// An operator is encountered
else {
while (!isEmpty(stack) && precedence(exp[i]) <= precedence(stack->array[stack->top]))
result[k++] = pop(stack);
push(stack, exp[i]);
}
}

// Pop all the operators from the stack


while (!isEmpty(stack))
result[k++] = pop(stack);

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>

// Definition of a tree node


typedef struct TreeNode {
int data;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;

// Function to create a new tree node


TreeNode* createNode(int data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

// Function to insert a node into the BST


TreeNode* insert(TreeNode* root, int data) {
if (root == NULL) {
return createNode(data);
}
if (data < root->data) {
root->left = insert(root->left, data);
} else {
root->right = insert(root->right, data);
}
return root;
}

// Function to find the minimum value in the BST


int findMin(TreeNode* root) {
if (root == NULL) {
printf("Tree is empty\n");
return -1; // Indicate that the tree is empty
}
TreeNode* current = root;
while (current->left != NULL) {
current = current->left;
}
return current->data;
}

// Function to find the maximum value in the BST


int findMax(TreeNode* root) {
if (root == NULL) {
printf("Tree is empty\n");
return -1; // Indicate that the tree is empty
}
TreeNode* current = root;
while (current->right != NULL) {
current = current->right;
}
return current->data;
}

// Function to perform an in-order traversal of the BST


void inorderTraversal(TreeNode* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
}

// Main function to test the BST operations


int main() {
TreeNode* root = NULL;

// Insert nodes into the BST


root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);

// Perform in-order traversal


printf("In-order traversal of the BST:\n");
inorderTraversal(root);
printf("\n");

// Find the minimum and maximum values


printf("Minimum value in the BST: %d\n", findMin(root));
printf("Maximum value in the BST: %d\n", findMax(root));

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>

// Definition of the AVL Tree Node structure


typedef struct Node {
int data;
int height;
struct Node *left;
struct Node *right;
} Node;

// Function to create a new node


Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->height = 1;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

// Function to get the height of a node


int height(Node *node) {
return (node == NULL) ? 0 : node->height;
}
// Function to get the balance factor of a node
int getBalance(Node *node) {
return (node == NULL) ? 0 : height(node->left) - height(node->right);
}

// Function for right rotation


Node* rightRotate(Node *y) {
Node *x = y->left;
Node *T2 = x->right;

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

// Return new root


return x;
}

// Function for left rotation


Node* leftRotate(Node *x) {
Node *y = x->right;
Node *T2 = y->left;

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

// Return new root


return y;
}

// Function to insert a node into the AVL tree


Node* insert(Node* node, int data) {
// 1. Perform the normal BST insert
if (node == NULL) {
return createNode(data);
}

if (data < node->data) {


node->left = insert(node->left, data);
} else if (data > node->data) {
node->right = insert(node->right, data);
} else {
// Duplicate keys are not allowed
return node;
}

// 2. Update the height of this ancestor node


node->height = 1 + (height(node->left) > height(node->right) ? height(node->left) :
height(node->right));

// 3. Get the balance factor of this ancestor node to check whether this node became
unbalanced
int balance = getBalance(node);

// If this node becomes unbalanced, then there are 4 cases

// Left Left Case


if (balance > 1 && data < node->left->data)
return rightRotate(node);

// Right Right Case


if (balance < -1 && data > node->right->data)
return leftRotate(node);

// Left Right Case


if (balance > 1 && data > node->left->data) {
node->left = leftRotate(node->left);
return rightRotate(node);
}

// Right Left Case


if (balance < -1 && data < node->right->data) {
node->right = rightRotate(node->right);
return leftRotate(node);
}

// Return the (unchanged) node pointer


return node;
}

// Function to perform preorder traversal of the AVL tree


void preorderTraversal(Node* root) {
if (root != NULL) {
printf("%d ", root->data);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
}
// Main function
int main() {
Node* root = NULL;

// Insert nodes into the AVL tree


root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 15);
root = insert(root, 25);
root = insert(root, 5);
root = insert(root, 1);

// Display the elements of the AVL tree in preorder


printf("Preorder traversal of the AVL tree:\n");
preorderTraversal(root);
printf("\n");

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;

// Function to initialize the heap


void initializeHeap(BinaryHeap *heap) {
heap->size = 0;
}

// Function to get the index of the parent


int parent(int i) {
return (i - 1) / 2;
}

// Function to get the index of the left child


int leftChild(int i) {
return 2 * i + 1;
}

// Function to get the index of the right child


int rightChild(int i) {
return 2 * i + 2;
}
// Function to swap two elements in the heap
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}

// Function to heapify-up (used after insertion)


void heapifyUp(BinaryHeap *heap, int index) {
while (index != 0 && heap->data[parent(index)] > heap->data[index]) {
swap(&heap->data[parent(index)], &heap->data[index]);
index = parent(index);
}
}

// Function to heapify-down (used after deletion)


void heapifyDown(BinaryHeap *heap, int index) {
int smallest = index;
int left = leftChild(index);
int right = rightChild(index);

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


smallest = left;
}

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


smallest = right;
}

if (smallest != index) {
swap(&heap->data[index], &heap->data[smallest]);
heapifyDown(heap, smallest);
}
}

// Function to insert a new element into the heap


void insert(BinaryHeap *heap, int value) {
if (heap->size == MAX_SIZE) {
printf("Heap is full\n");
return;
}

heap->data[heap->size] = value;
heap->size++;
heapifyUp(heap, heap->size - 1);
}

// Function to remove the minimum element (root) from the heap


int removeMin(BinaryHeap *heap) {
if (heap->size <= 0) {
printf("Heap is empty\n");
return -1; // Or some sentinel value
}

int root = heap->data[0];


heap->data[0] = heap->data[heap->size - 1];
heap->size--;
heapifyDown(heap, 0);

return root;
}

// Function to display the elements of the heap


void displayHeap(BinaryHeap *heap) {
for (int i = 0; i < heap->size; i++) {
printf("%d ", heap->data[i]);
}
printf("\n");
}

// Main function to test the heap operations


int main() {
BinaryHeap heap;
initializeHeap(&heap);

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

printf("Removed minimum element: %d\n", removeMin(&heap));


printf("Heap elements after removing the minimum element:\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>

#define V 9 // Number of vertices in the graph

// Function to find the vertex with the minimum distance value


int minDistance(int dist[], bool sptSet[]) {
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;
}

// Function to implement Dijkstra's algorithm


void dijkstra(int graph[V][V], int src) {
int dist[V]; // dist[i] holds the shortest distance from src to i
bool sptSet[V]; // sptSet[i] will be true if vertex i is included in shortest path tree

// Initialize distances and sptSet


for (int i = 0; i < V; i++) {
dist[i] = INT_MAX;
sptSet[i] = false;
}

dist[src] = 0; // Distance from source to itself is always 0

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


// Pick the minimum distance vertex from the set of vertices not yet processed
int u = minDistance(dist, sptSet);

// Mark the picked vertex as processed


sptSet[u] = true;

// 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];
}
}
}

// Print the constructed distance array


printf("Vertex\t Distance from Source\n");
for (int i = 0; i < V; i++) {
printf("%d \t\t %d\n", i, dist[i]);
}
}

// Main function to test the algorithm


int main() {
// Example graph represented as an adjacency matrix
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}
};

dijkstra(graph, 0); // Running Dijkstra's algorithm from vertex 0

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;

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


if (!mstSet[v] && key[v] < min) {
min = key[v];
min_index = v;
}
}
return min_index;
}

// Function to implement Prim's Algorithm


void primMST(int graph[V][V]) {
int parent[V]; // Array to store the MST
int key[V]; // Key values to pick the minimum weight edge
bool mstSet[V]; // Array to check if vertex is included in MST

// Initialize all keys as INFINITE and mstSet as false


for (int i = 0; i < V; i++) {
key[i] = INT_MAX;
mstSet[i] = false;
}

// Always include the first vertex in MST


key[0] = 0; // Make key 0 so that this vertex is picked as the first vertex
parent[0] = -1; // First node is always the root of MST

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


// Pick the minimum key vertex from the set of vertices not yet processed
int u = minKey(key, mstSet);

// Add the picked vertex to the MST set


mstSet[u] = true;

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

// Print the constructed MST


printf("Edge \tWeight\n");
for (int i = 1; i < V; i++) {
printf("%d - %d \t%d \n", parent[i], i, graph[i][parent[i]]);
}
}

// Main function to test the algorithm


int main() {
// Example graph represented as an adjacency matrix
int graph[V][V] = {
{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0}
};

primMST(graph); // Running Prim's Algorithm

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
}

// Main function to test the linear search


int main() {
int arr[] = {34, 7, 23, 32, 5, 62}; // Example array
int size = sizeof(arr) / sizeof(arr[0]);
int target, result;

printf("Enter the number to search: ");


scanf("%d", &target);

result = linearSearch(arr, size, target);

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;

while (low <= high) {


int mid = low + (high - low) / 2;

// Check if target is present at mid


if (arr[mid] == target) {
return mid; // Target found at index mid
}

// If target is greater, ignore the left half


if (arr[mid] < target) {
low = mid + 1;
}
// If target is smaller, ignore the right half
else {
high = mid - 1;
}
}

// Target not found


return -1;
}

// Main function to test the binary search


int main() {
int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; // Sorted array
int size = sizeof(arr) / sizeof(arr[0]);
int target, result;

printf("Enter the number to search: ");


scanf("%d", &target);

result = binarySearch(arr, size, target);

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

// Function to print an array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Main function to test insertion sort
int main() {
int arr[] = {12, 11, 13, 5, 6}; // Example array
int size = sizeof(arr) / sizeof(arr[0]);

printf("Original array:\n");
printArray(arr, size);

insertionSort(arr, size);

printf("Sorted array in ascending order:\n");


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

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


minIndex = i; // Assume the current position as the minimum

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

// Swap the found minimum element with the element at position i


if (minIndex != i) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}

// Function to print an array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

// Main function to test selection sort


int main() {
int arr[] = {64, 25, 12, 22, 11}; // Example array
int size = sizeof(arr) / sizeof(arr[0]);

printf("Original array:\n");
printArray(arr, size);

selectionSort(arr, size);

printf("Sorted array in ascending order:\n");


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

// Create temporary arrays


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

// Copy data to temporary arrays


for (int i = 0; i < n1; i++)
L[i] = arr[left + i];
for (int j = 0; j < n2; j++)
R[j] = arr[mid + 1 + j];

// Merge the temporary arrays back into arr[left..right]


int i = 0; // Initial index of first subarray
int j = 0; // Initial index of second subarray
int k = left; // Initial index of merged subarray

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


if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}

// Copy the remaining elements of L[], if any


while (i < n1) {
arr[k] = L[i];
i++;
k++;
}

// Copy the remaining elements of R[], if any


while (j < n2) {
arr[k] = R[j];
j++;
k++;
}

// Free the temporary arrays


free(L);
free(R);
}

// Function to implement merge sort


void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;

// Recursively sort first and second halves


mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);

// Merge the sorted halves


merge(arr, left, mid, right);
}
}

// Function to print an array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Main function to test merge sort
int main() {
int arr[] = {12, 11, 13, 5, 6, 7}; // Example array
int size = sizeof(arr) / sizeof(arr[0]);

printf("Original array:\n");
printArray(arr, size);

mergeSort(arr, 0, size - 1);

printf("Sorted array in ascending order:\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

// Hash function to compute the index


int hashFunction(int key) {
return key % TABLE_SIZE;
}

// Function to insert a key into the hash table


void insert(int hashTable[], int key) {
int index = hashFunction(key);
int startIndex = index;
// Linear probing to find an empty slot
while (hashTable[index] != EMPTY && hashTable[index] != DELETED) {
index = (index + 1) % TABLE_SIZE;
if (index == startIndex) {
printf("Hash table is full\n");
return;
}
}
hashTable[index] = key;
}

// Function to search for a key in the hash table


int search(int hashTable[], int key) {
int index = hashFunction(key);
int startIndex = index;

while (hashTable[index] != EMPTY) {


if (hashTable[index] == key) {
return index;
}
index = (index + 1) % TABLE_SIZE;
if (index == startIndex) {
return -1;
}
}
return -1;
}

// Function to delete a key from the hash table


void delete(int hashTable[], int key) {
int index = search(hashTable, key);
if (index != -1) {
hashTable[index] = DELETED;
} else {
printf("Key not found\n");
}
}
// Function to print the hash table
void printHashTable(int hashTable[]) {
for (int i = 0; i < TABLE_SIZE; i++) {
if (hashTable[i] == EMPTY) {
printf("Slot %d: EMPTY\n", i);
} else if (hashTable[i] == DELETED) {
printf("Slot %d: DELETED\n", i);
} else {
printf("Slot %d: %d\n", i, hashTable[i]);
}
}
}
// Main function to test the linear probing hash table
int main() {
int hashTable[TABLE_SIZE];

// Initialize hash table


for (int i = 0; i < TABLE_SIZE; i++) {
hashTable[i] = EMPTY;
}

// Insert elements into the hash table


insert(hashTable, 10);
insert(hashTable, 20);
insert(hashTable, 30);
insert(hashTable, 40);
insert(hashTable, 50);

printf("Hash Table after insertions:\n");


printHashTable(hashTable);

// Search for elements


int key = 20;
int index = search(hashTable, key);
if (index != -1) {
printf("Key %d found at index %d\n", key, index);
} else {
printf("Key %d not found\n", key);
}

// Delete an element
delete(hashTable, 30);
printf("Hash Table after deletion of key 30:\n");
printHashTable(hashTable);

// Search for deleted element


key = 30;
index = search(hashTable, key);
if (index != -1) {
printf("Key %d found at index %d\n", key, index);
} else {
printf("Key %d not found\n", key);
}

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

// Hash function to compute the index


int hashFunction(int key) {
return key % TABLE_SIZE;
}

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

while (hashTable[(index + i * i) % TABLE_SIZE] != EMPTY &&


hashTable[(index + i * i) % TABLE_SIZE] != DELETED) {
i++;
if (i == TABLE_SIZE) {
printf("Hash table is full\n");
return;
}
}
hashTable[(index + i * i) % TABLE_SIZE] = key;
}

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

while (hashTable[(index + i * i) % TABLE_SIZE] != EMPTY) {


if (hashTable[(index + i * i) % TABLE_SIZE] == key) {
return (index + i * i) % TABLE_SIZE;
}
i++;
if (i == TABLE_SIZE) {
return -1;
}
}
return -1;
}

// 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");
}
}

// Function to print the hash table


void printHashTable(int hashTable[]) {
for (int i = 0; i < TABLE_SIZE; i++) {
if (hashTable[i] == EMPTY) {
printf("Slot %d: EMPTY\n", i);
} else if (hashTable[i] == DELETED) {
printf("Slot %d: DELETED\n", i);
} else {
printf("Slot %d: %d\n", i, hashTable[i]);
}
}
}

// Main function to test the quadratic probing hash table


int main() {
int hashTable[TABLE_SIZE];

// Initialize hash table


for (int i = 0; i < TABLE_SIZE; i++) {
hashTable[i] = EMPTY;
}

// Insert elements into the hash table


insert(hashTable, 10);
insert(hashTable, 20);
insert(hashTable, 30);
insert(hashTable, 40);
insert(hashTable, 50);

printf("Hash Table after insertions:\n");


printHashTable(hashTable);

// Search for elements


int key = 20;
int index = search(hashTable, key);
if (index != -1) {
printf("Key %d found at index %d\n", key, index);
} else {
printf("Key %d not found\n", key);
}

// Delete an element
delete(hashTable, 30);
printf("Hash Table after deletion of key 30:\n");
printHashTable(hashTable);

// Search for deleted element


key = 30;
index = search(hashTable, key);
if (index != -1) {
printf("Key %d found at index %d\n", key, index);
} else {
printf("Key %d not found\n", key);
}

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>

// Function to perform counting sort based on the digit represented by exp


void countingSort(int arr[], int size, int exp) {
int* output = (int*)malloc(size * sizeof(int));
int count[10] = {0}; // Initialize count array with zeroes

// Store count of occurrences of each digit


for (int i = 0; i < size; i++) {
count[(arr[i] / exp) % 10]++;
}

// Change count[i] to contain the actual position of this digit in output[]


for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}

// Build the output array


for (int i = size - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
// Copy the output array to arr[], so that arr[] contains sorted numbers
for (int i = 0; i < size; i++) {
arr[i] = output[i];
}

free(output);
}

// Function to get the maximum value in the array


int getMax(int arr[], int size) {
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}

// Function to perform radix sort on the array


void radixSort(int arr[], int size) {
int max = getMax(arr, size);

// Perform counting sort for every digit place


for (int exp = 1; max / exp > 0; exp *= 10) {
countingSort(arr, size, exp);
}
}

// Function to print the array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

// Main function to test radix sort


int main() {
int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
int size = sizeof(arr) / sizeof(arr[0]);

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>

// Function to perform Shell Sort


void shellSort(int arr[], int size) {
// Initialize the gap size
for (int gap = size / 2; gap > 0; gap /= 2) {
// Perform a modified insertion sort for this gap size
for (int i = gap; i < size; i++) {
int temp = arr[i];
int j;

// Shift elements of arr[0..i-gap] that are greater than temp


// to their new positions
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
}

// Function to print the array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

// Main function to test Shell Sort


int main() {
int arr[] = {12, 34, 54, 2, 3};
int size = sizeof(arr) / sizeof(arr[0]);

printf("Original array:\n");
printArray(arr, size);

shellSort(arr, size);

printf("Sorted array:\n");
printArray(arr, size);

return 0;
}

Output:

Inference:

Result:

You might also like