DS LAB Mannual
DS LAB Mannual
2
Experiment No.1
Theory: A stack data structure can be implemented using a one-dimensional array. But stack implemented
using array stores only a fixed number of data values. This implementation is very simple. Just define a one-
dimensional array of specific size and insert or delete the values into that array by using LIFO principle with
the help of a variable called 'top'. Initially, the top is set to -1. Whenever we want to insert a value into the
stack, increment the top value by one and then insert. Whenever we want to delete a value from the stack, then
delete the top value and decrement the top value by one.
3
Display () - display the element of the stack:-
We can use the following steps to display the elements of a stack...
Step 1 - Check whether stack is EMPTY. (top == -1)
Step 2 - If it is EMPTY, then display "Stack is EMPTY!!!" and terminate the function.
Step 3 - If it is NOT EMPTY, then define a variable 'i' and initialize with top. Display stack[i] value and
decrement i value by one (i--).
Step 3 - Repeat above step until i value becomes '0'.
4
Program:
#include<stdio.h>
int stack[100],choice,n,top,x,i;
void push(void);
void pop(void);
void display(void);
int main()
{
//clrscr();
top=-1;
printf("\n Enter the size of STACK[MAX=100]:");
scanf("%d",&n);
printf("\n\t STACK OPERATIONS USING ARRAY");
printf("\n\t ");
printf("\n\t 1.PUSH\n\t 2.POP\n\t 3.DISPLAY\n\t 4.EXIT");
do
{
printf("\n Enter the Choice:");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
push();
break;
}
case 2:
{
pop();
break;
}
case 3:
{
display();
break;
}
case 4:
{
printf("\n\t EXIT POINT ");
break;
}
default:
{
5
printf ("\n\t Please Enter a Valid Choice(1/2/3/4)");
}
}
}
while(choice!=4);
return 0;
}
void push()
{
if(top>=n-1)
{
printf("\n\tSTACK is over flow");
}
else
{
printf(" Enter a value to be pushed:");
scanf("%d",&x);
top++;
stack[top]=x;
}
}
void pop()
{
if(top<=-1)
{
printf("\n\t Stack is under flow");
}
else
{
printf("\n\t The popped elements is %d",stack[top]);
top--;
}
}
void display()
{
if(top>=0)
{
printf("\n The elements in STACK \n");
for(i=top; i>=0; i--)
printf("\n%d",stack[i]);
printf("\n Press Next Choice");
}
6
else
{
printf("\n The STACK is empty");
}
7
Output:
8
Experiment No.2
● At first, the compiler scans the expression to evaluate the expression b / c, then scans the expression
again to add a to it. The result is then subtracted with d after another scan.
● This repeated scanning makes the process very inefficient and time consuming. It will be much easier
if the expression is converted to postfix (or prefix) before evaluation.
● The corresponding expression in postfix form is: abc/+d-. The postfix expressions can be easily
evaluated using a stack.
● If the precedence of the scanned operator is greater than the precedence of the operator in the top of
the stack(or the stack is empty or if the stack contains a ‘(‘ ), push it.
● Else, Pop all operators from the stack whose precedence is greater than or equal to that of the scanned
operator. Then, push the scanned operator to the top of the stack. (If you encounter parenthesis while
popping then stop there and push the scanned operator in the stack.)
4. If the scanned character is ‘(‘, push it to the stack.
5. If the scanned character is ‘)’, pop the stack and and output characters until ‘(‘ is encountered, and discard
both the parenthesis.
9
Program Code:
#include<stdio.h>
#include<ctype.h>
char stack[100];
int top = -1;
void push(char x)
{
stack[++top] = x;
char pop()
{
if(top == -1)
return -1;
else
return stack[top--];
int priority(char x)
{
if(x == '(')
return 0;
10
}
int main()
char exp[100];
char *e, x;
printf("Enter the Infix expression : ");
scanf("%s",exp);
printf("Equivalent Postfix expression : ");
e = exp;
while(*e != '\0')
{
if(isalnum(*e))
printf("%c ",*e);
else
{
while(priority(stack[top]) >= priority(*e))
printf("%c ",pop());
push(*e);
}
e++;
}
11
while(top != -1)
{
printf("%c",pop());
}return 0;
12
Output:
13
Experiment No.3
As Postfix expression is without parenthesis and can be evaluated as two operands and an operator at a time,
this becomes easier for the compiler and the computer to handle.
1. While reading the expression from left to right, push the element in the stack if it is an operand.
2. Pop the two operands from the stack, if the element is an operator and then evaluate it.
3. Push back the result of the evaluation. Repeat it till the end of the expression.
Algorithm
[End If]
6) END
14
Program Code:
#include<stdio.h>
#include<ctype.h>
int stack[20];
int top = -1;
void push(int x)
{
stack[++top] = x;
int pop()
{
return stack[top--];
}
int main()
char exp[20];
char *e;
int n1,n2,n3,num;
{
if(isdigit(*e))
{
num = *e - 48;
push(num);
}
else
15
{
n1 = pop();
n2 = pop();
switch(*e)
{
case '+':
n3 = n1 + n2;
break;
}
case '-':
n3 = n2 - n1;
break;
}
case '*':
n3 = n1 * n2;
break;
}
case '/':
{
n3 = n2 / n1;
break;
}
}
push(n3);
}
e++;
}
16
printf("\nThe result of expression %s = %d\n\n",exp,pop());
return 0;
}
17
Output:
18
Experiment No.4
1. Expression Evalution: -
Stack data structure is used for evaluating the given expression. For example, consider the following
expression
5 * ( 6 + 2 ) - 12 / 4
Since parenthesis has the highest precedence among the arithmetic operators, ( 6 +2 ) = 8 will be evaluated
first. Now, the expression becomes
5 * 8 - 12 / 4
* and / have equal precedence and their associativity is from left-to-right. So, start evaluating the expression
from left-to-right.
5 * 8 = 40 and 12 / 4 = 3
Now, the expression becomes
40 - 3
And the value returned after the subtraction operation is 37.
2. Parenthesis Matching: -
Given an expression, you have to find if the parenthesis is either correctly matched or not. For example,
consider the expression ( a + b ) * ( c + d ).
19
In the above expression, the opening and closing of the parenthesis are given properly and hence it is said to
be a correctly matched parenthesis expression. Whereas, the expression, (a + b * [c + d ) is not a valid
expression as the parenthesis are incorrectly given.
3. Expression Conversion: -
Converting one form of expressions to another is one of the important applications of stacks.
• Infix to prefix
• Infix to postfix
• Prefix to Infix
• Prefix to Postfix
• Postfix to Infix
• Postfix to Infix
4. Memory Management: -
The assignment of memory takes place in contiguous memory blocks. We call this stack memory allocation
because the assignment takes place in the function call stack. The size of the memory to be allocatedis known
to the compiler. When a function is called, its variables get memory allocated on the stack. When the function
call is completed, the memory for the variables is released. All this happens with the help of somepredefined
routines in the compiler. The user does not have to worry about memory allocation and release of stack
variables. The memory to be allocated to these variables is known to the compiler and when the functionis
called, the allocation is done and when the function terminates, the memory is released.
5. Backtracking Problems: -
The basic strategy we will use to solve this problem is to use backtracking. In this particular case,
backtracking means we will perform a safe move for a queen at the time we make the move. Later, however,
we find that we are stuck and there is no safe movement for the next Queen, whom we are trying to put on the
blackboard, so we have to go back.
This means we return to the queen's previous move, undo this step, and continue to search for a safe place to
place this queen.
We will use the stack to remember where we placed queens on the board, and if we need to make a backup,
the queen at the top of the stack will be popped, and we will use the position of that queen to resume the search
for next safe location.
20
Experiment No.5
Generally, the value of the element itself is considered for assigning the priority.
For example, The element with the highest value is considered as the highest priority element. However, in
other cases, we can assume the element with the lowest value as the highest priority element. In other cases,
we can set priorities according to our needs.
Priority queue can be implemented using an array, a linked list, a heap data structure, or a binary search tree.
Among these data structures, heap data structure provides an efficient implementation of priority queues.
Hence, we will be using the heap data structure to implement the priority queue in this tutorial. A max-heap
is implement is in the following operations. If you want to learn more about it, please visit max-heap and
mean-heap.
Priority Queue Operation: Basic operations of a priority queue are inserting, removing, and peeking
elements.
Inserting an element into a priority queue (max-heap) is done by the following steps.
21
• Insert the new element at the end of the tree.
If there is no node,
create a newNode.
22
insert the newNode at the end (last node from left to right.)
For Min Heap, the above algorithm is modified so that parentNode is always smaller than newNode.
23
• Remove the last element.
24
remove noteToBeDeleted
For Min Heap, the above algorithm is modified so that the both childNodeare smaller than currentNode.
Peek operation returns the maximum element from Max Heap or minimum element from Min Heap
without deleting the node.
return rootNode
Extract-Max returns the node with maximum value after removing it from a Max Heap whereas
Extract-Min returns the node with minimum value after removing it from Min Heap.
25
Program Code:
mport java.util.ArrayList;
class Heap {
// Find the largest among root, left child and right child
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < size && hT.get(l) > hT.get(largest))
largest = l;
if (r < size && hT.get(r) > hT.get(largest))
largest = r;
if (largest != i) {
heapify(hT, largest);
}
26
hT.add(newNum);
} else {
hT.add(newNum);
int i;
for (i = 0; i < size; i++) {
if (num == hT.get(i))
break;
hT.set(size - 1, temp);
hT.remove(size - 1);
for (int j = size / 2 - 1; j >= 0; j--) {
heapify(hT, j);
}
System.out.println();
}
// Driver code
public static void main(String args[]) {
h.insert(array, 4);
h.insert(array, 9);
h.insert(array, 5);
h.insert(array, 2);
h.printArray(array, size);
h.deleteNode(array, 4);
System.out.println("After deleting an element: ");
h.printArray(array, size);
}
28
Output:
29
Experiment No.6
Doubly Linked List is a variation of Linked list in which navigation is possible in both ways, either forward
and backward easily as compared to Single Linked List. Following are the important terms to understand the
concept of doubly linked list.
• Link − Each link of a linked list can store a data called an element.
• Next − Each link of a linked list contains a link to the next link called Next.
• Prev − Each link of a linked list contains a link to the previous link called Prev.
• LinkedList − A Linked List contains the connection link to the first link called First and to the last
link called Last.
30
As per the above illustration, following are the important points to be considered.
• Doubly Linked List contains a link element called first and last.
• Each link carries a data field(s) and two link fields called next and prev.
• Each link is linked with its next link using its next link.
• Each link is linked with its previous link using its previous link.
• The last link carries a link as null to mark the end of the list.
Basic Operations
Following are the basic operations supported by a list.
• Insertion − Adds an element at the beginning of the list.
• Deletion − Deletes an element at the beginning of the list.
• Insert Last − Adds an element at the end of the list.
• Delete Last − Deletes an element from the end of the list.
• Insert After − Adds an element after an item of the list.
• Delete − Deletes an element from the list using the key.
• Display forward − Displays the complete list in a forward manner.
• Display backward − Displays the complete list in a backward manner.
31
Program Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
int data;
int key;
};
bool isEmpty() {
int length() {
int length = 0;
32
for(current = head; current != NULL; current = current->next){
length++;
return length;
void displayForward() {
printf("\n[ ");
while(ptr != NULL) {
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
printf(" ]");
void displayBackward() {
printf("\n[ ");
33
while(ptr != NULL) {
//print data
printf("(%d,%d) ",ptr->key,ptr->data)
//create a link
link->key = key;
link->data = data;
if(isEmpty()) {
last = link;
} else {
head->prev = link;
34
link->next = head;
head = link;
//create a link
link->key = key;
link->data = data;
if(isEmpty()) {
last = link;
} else {
last->next = link;
link->prev = last;
35
//point last to new last node
last = link;
if(head->next == NULL){
last = NULL;
} else {
head->next->prev = NULL;
head = head->next;
return tempLink;
36
struct node* deleteLast() {
if(head->next == NULL) {
head = NULL;
} else {
last->prev->next = NULL;
last = last->prev;
return tempLink;
37
struct node* previous = NULL;
if(head == NULL) {
return NULL;
}
//navigate through list
while(current->key != key) {
if(current->next == NULL) {
return NULL;
} else {
previous = current;
current = current->next;
if(current == head) {
head = head->next;
} else {
38
current->prev->next = current->next;
if(current == last) {
last = current->prev;
} else {
current->next->prev = current->prev;
return current;
if(head == NULL) {
return false;
while(current->key != key) {
if(current->next == NULL) {
return false;
39
} else {
current = current->next;
//create a link
newLink->key = newKey;
newLink->data = data;
if(current == last) {
newLink->next = NULL;
last = newLink;
} else {
newLink->next = current->next;
current->next->prev = newLink;
newLink->prev = current;
current->next = newLink;
return true;
void main() {
insertFirst(1,10);
40
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
displayForward();
printf("\n");
displayBackward();
deleteFirst();
displayForward();
deleteLast();
displayForward();
insertAfter(4,7, 13);
displayForward();
41
printf("\nList , after delete key(4) : ");
delete(4);
displayForward();
42
Output:
43
Experiment No.7
The storage requirement of linked representation of a queue with n elements is o(n) while the time requirement
for operations is o(1).
In a linked queue, each node of the queue consists of two parts i.e. data part and the link part. Each element
of the queue points to its immediate next element in the memory.
In the linked queue, there are two pointers maintained in the memory i.e. front pointer and rear pointer. The
front pointer contains the address of the starting element of the queue while the rear pointer contains the
address of the last element of the queue.
Insertion and deletions are performed at rear and front end respectively. If front and rear both are NULL, it
indicates that the queue is empty.
There are two basic operations which can be implemented on the linked queues. The operations are Insertion
and Deletion.
Insert operation:
The insert operation append the queue by adding an element to the end of the queue. The new element will be
the last element of the queue
44
Algorithm:
Step 1: Allocate the space for the new node PTR
Step 2: SET PTR -> DATA = VAL
Step 3: IF FRONT = NULL
SET FRONT = REAR = PTR
SET FRONT -> NEXT = REAR -> NEXT = NULL
ELSE
SET REAR -> NEXT = PTR
SET REAR = PTR
SET REAR -> NEXT = NULL
[END OF IF]
Step 4: END
Deletion:
Deletion operation removes the element that is first inserted among all the queue elements. Firstly, we need to
check either the list is empty or not. The condition front == NULL becomes true if the list is empty, in thiscase
, we simply write underflow on the console and make exit.
Algorithm:
45
Program Code:
#include<stdio.h>
#include<stdlib.h>
struct node
int data;
};
void insert();
void delete();
void display();
void main ()
int choice;
while(choice != 4)
printf("\n*************************Main Menu*****************************\n");
printf("\n=================================================================\n");
46
scanf("%d",& choice);
switch(choice)
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
display();
break;
case 4:
exit(0);
break;
default:
void insert()
47
int item;
if(ptr == NULL)
printf("\nOVERFLOW\n");
return;
else
printf("\nEnter value?\n");
scanf("%d",&item);
if(front == NULL)
front = ptr;
rear = ptr;
else
48
rear = ptr;
rear->next = NULL;
void delete ()
if(front == NULL)
printf("\nUNDERFLOW\n");
return;
else
ptr = front;
free(ptr);
void display()
49
ptr = front;
if(front == NULL)
printf("\nEmpty queue\n");
else
while(ptr != NULL)
50
Output:
51
Experiment No.8
Aim: Implement Graph Traversal techniques: a) Depth First Search b) Breadth First Search
Theory: Graph traversal is a technique used for a searching vertex in a graph. The graph traversal is also
used to decide the order of vertices is visited in the search process. A graph traversal finds the edges to be used
in the search process without creating loops. That means using graph traversal we visit all the vertices ofthe
graph without getting into a looping path.
There are two graph traversal techniques and they are as follows...
DFS traversal of a graph produces a spanning tree as the final result. Spanning Tree is a graph without loops.
We use Stack data structure with maximum size of total number of vertices in the graph to implement DFS
traversal.
BFS traversal of a graph produces a spanning tree as a final result. Spanning Tree is a graph without loops.
We use Queue data structure with maximum size of total number of vertices in the graph to implement BFS
traversal.
53
Program Code:
#include<stdio.h>
int q[20],top=-1,front=-1,rear=-1,a[20][20],vis[20],stack[20];
int delete();
void main()
{
int n,i,s,ch,j;
char c,dummy;
printf("ENTER THE NUMBER VERTICES ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
printf("ENTER 1 IF %d HAS A NODE WITH %d ELSE 0 ",i,j);
scanf("%d",&a[i][j]);
}
}
printf("THE ADJACENCY MATRIX IS\n");
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
printf(" %d",a[i][j]);
54
}
printf("\n");
}
do{
for(i=1;i<=n;i++)
vis[i]=0;
printf("\nMENU");
printf("\n1.B.F.S");
printf("\n2.D.F.S");
scanf("%d",&s);
switch(ch)
{
case 1:bfs(s,n);
break;
case 2:
dfs(s,n);
break;
}while((c=='y')||(c=='Y'));
}
int p,i;
55
add(s);
vis[s]=1;
p=delete();
if(p!=0)
printf(" %d",p);
while(p!=0)
{
for(i=1;i<=n;i++)
if((a[p][i]!=0)&&(vis[i]==0))
add(i);
vis[i]=1;
}
p=delete();
if(p!=0)
printf(" %d ",p);
for(i=1;i<=n;i++)
if(vis[i]==0)
bfs(i,n);
}
void add(int item)
{
if(rear==19)
printf("QUEUE FULL");
else
{
if(rear==-1)
{
q[++rear]=item;
56
front++;
}
else
q[++rear]=item;
}
}
int delete()
int k;
if((front>rear)||(front==-1))
return(0);
else
{
k=q[front++];
return(k);
int i,k;
push(s);
vis[s]=1;
k=pop();
if(k!=0)
printf(" %d ",k);
while(k!=0)
{
for(i=1;i<=n;i++)
if((a[k][i]!=0)&&(vis[i]==0))
57
{
push(i);
vis[i]=1;
}
k=pop();
if(k!=0)
printf(" %d ",k);
}
for(i=1;i<=n;i++)
if(vis[i]==0)
dfs(i,n);
}
void push(int item)
{
if(top==19){
stack[++top]=item;}
}
int pop()
int k;
if(top==-1)
return(0);
else
{
k=stack[top--];
return(k);
58
Output:
59
Experiment No.9
Before giving you the code for establishing a binary search in C, let’s first understand how exactly the
algorithm works.
In case the target element is less than the middle element (considering the array follows an ascending order)
of the array then the second half of the array is discarded and the search continues by dividing the first half.
The process is the same when the target element is greater than the middle element, only, in this case, the first
half of the array is discarded before continuing with the search. The iteration repeats until a match for the
target element is found.
If the requirements ask for using binary search on an unsorted array, then it needs to be sorted first before
using the binary search algorithm on it. For doing so, you can make use of some sorting technique, such as the
bubble sort or the merge sort.
NOTE: - The code mentioned below assumes that the input numbers follow an ascending order!
The binary search is not restricted to searching for an element in a sorted sequence; if it were, the algorithm
would be considered trivial and uninteresting. An interesting application of the algorithm is binary search on
the result. For example, imagine that we want to find the minimum size needed for a square office that must
freely accommodate all the employees of a company. We can perform a binary search for that size rather than
sequentially checking all the possible sizes. We usually estimate the minimum and maximum sizes over which
we do a binary search. Next, we just check some middle value and the interval can be halved again, and so on.
That’s a lot of saved time.
60
Program Code:
#include<stdio.h>
int main()
scanf("%d",&n);
printf("Enter %d integers:\n", n);
for (c = 0; c < n; c++)
scanf("%d",&array[c]);
printf("Enter the value to find:\n");
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last) {
first = middle + 1;
else if (array[middle] == search) {
printf("%d is present at index %d.\n", search, middle+1);
break;
} else
last = middle - 1;
middle = (first + last)/2;
61
Output:
62
PRACTICAL NO – 10
Theory :
Linked List is a collection of interconnected nodes that together represent a sequence. Connected node
means if you have access of a node, then you can get access to the next nodes even though they are not
located in consecutive memory locations.
For singly linked list, you can traverse the list only in one direction. The diagram below shows an example
of a singly linked list.
CODE :
#include <stdio.h>
#include <stdlib.h>
struct node
{
int val;
struct node *next;
};
/*Print the linked list*/
void print_list(struct node *head)
{
printf("H->");
while(head)
{
printf("%d->", head->val);
head = head->next;
}
printf("|||\n");
}
/*Insert an element at the front of the list*/
void insert_front(struct node **head, int value)
{
struct node * new_node = NULL;
/*Allocating memory for the new node*/
new_node = (struct node *)malloc(sizeof(struct node)); if (new_node == NULL)
{
printf("Failed to insert element. Out of memory");
}
new_node->val
/*Pointing the new node to where head is currently pointing to*/
new_node->next = *head;
/*Pointing head to new node.*/
*head = new_node;
}
void main()
{ int count = 0, i, val;
struct node * head = NULL;
printf("Enter number of elements: ");
scanf("%d", &count);
for (i = 0; i < count; i++)
{
63
printf("Enter %dth element: ", i);
scanf("%d", &val);
insert_front(&head, val);
}
printf("Linked List: ");
print_list(head);
}
OUTPUT –
64
64