Download as pdf or txt
Download as pdf or txt
You are on page 1of 65

IMS ENGINEERING COLLEGE

Lab Manual
Data Structures Using C Lab (KCS-351)

Course: B.Tech Computer Science & Engineering


(2nd Year, ODD Semester)

Affiliated from APJ Abdul Kalam Technical University, Lucknow, U.P

Prepared by:
Faculty Name: Prof. Ravi Shankar Pal
Designation: Assistant Professor
Department: Information Technology
Department Vision and Mission

VISION

To be recognized as a Centre of Excellence imparting quality education and creating


new opportunities for students to meet the challenges of technological development in
Computer Science & Engineering

MISSION
• To promote technical proficiency by adopting effective teaching learning processes.
• To provide environment & opportunity for students to bring out their inherent
talents for all round development.
• To promote latest technologies in Computer Science & Engineering and across
disciplines in order to serve the needs of Industry, Government, Society, and the
scientific community.
• To educate students to be Successful, Ethical and Effective problem-solvers and Life-
Long learners who will contribute positively to the society.
List of Program Outcomes
Engineering Graduates will be able to:
1. Engineering knowledge: Apply the knowledge of mathematics, science, engineering fundamentals, and an
engineering specialization to the solution of complex engineering problems.
2. Problem analysis: Identify, formulate, review research literature, and analyze complex engineering problems
reaching substantiated conclusions using first principles of mathematics, natural sciences, and engineering
sciences.

3. Design/development of solutions: Design solutions for complex engineering problems and design system
components or processes that meet the specified needs with appropriate consideration for the public health
and safety, and the cultural, societal, and environmental considerations.

4. Conduct investigations of complex problems: Use research-based knowledge and research methods including
design of experiments, analysis and interpretation of data, and synthesis of the information to provide valid
conclusions.

5. Modern tool usage: Create, select, and apply appropriate techniques, resources, and modern engineering and
IT tools including prediction and modelling to complex engineering activities with an understanding of the
limitations.

6. The engineer and society: Apply reasoning informed by the contextual knowledge to assess societal, health,
safety, legal and cultural issues and the consequent responsibilities relevant to the professional engineering
practice.

7. Environment and sustainability: Understand the impact of the professional engineering solutions in societal
and environmental contexts, and demonstrate the knowledge of, and need for sustainable development.

8. Ethics: Apply ethical principles and commit to professional ethics and responsibilities and norms of the
engineering practice.

9. Individual and team work: Function effectively as an individual, and as a member or leader in diverse teams,
and in multidisciplinary settings.

10. Communication: Communicate effectively on complex engineering activities with the engineering community
and with society at large, such as, being able to comprehend and write effective reports and design
documentation, make effective presentations, and give and receive clear instructions.
11. Project management and finance: Demonstrate knowledge and understanding of the engineering and
management principles and apply these to one’s own work, as a member and leader in a team, to manage
projects and in multidisciplinary environments.

12. Life-long learning: Recognize the need for, and have the preparation and ability to engage in independent and
life-long learning in the broadest context of technological change.
Program Educational Objectives
PEO1: Graduates of the program will be able to apply fundamental principles of engineering in
problem solving and understand the role of computing in multiple disciplines.
PEO 2: Graduates will learn to apply various computational techniques & tools for developing
solutions & projects in real world.
PEO3:Be employed as computer science professionals beyond entry-level positions or be making
satisfactory progress in graduate programs
PEO4:Demonstrate that they can function, communicate, collaborate and continue to learn
effectively as ethically and socially responsible computer science professionals.
Program Specific Outcomes (PSO)
By the completion of program the student will have following Program specific outcomes.

1. Foundation of Computer System: Ability to understand the principles and working of computer
systems.

2. Foundations of Software development: Possess professional skills and knowledge of software


design process. Familiarity and practical competence with a broad range of programming language
and open source platforms.

3. Foundation of mathematical concepts: Ability to apply mathematical methodologies to solve


computation task, model real world problem using appropriate data structure and suitable
algorithm.

4. Applications of Computing and Research Ability: Ability to use knowledge in various domains to
identify research gaps and hence to provide solution to new ideas and innovations.
Data Structures Using C Lab (KCS-351)
University Syllabus

Write C Programs to illustrate the concept of the following:


1. Sorting Algorithms-Non-Recursive.
2. Sorting Algorithms-Recursive.
3. Searching Algorithm.
4. Implementation of Stack using Array.
5. Implementation of Queue using Array.
6. Implementation of Circular Queue using Array.
7. Implementation of Stack using Linked List.
8. Implementation of Queue using Linked List.
9. Implementation of Circular Queue using Linked List.
10. Implementation of Tree Structures, Binary Tree, Tree Traversal, Binary Search Tree, Insertion and Deletion
in BST.
11. Graph Implementation, BFS, DFS, Minimum cost spanning tree, shortest path algorithm
Data Structures Using C Lab (KCS-351)
Course Outcomes

CO CO Statement POs Mapped

1 Interpret and compute asymptotic notations PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


of an algorithm to analyze the consumption
of resources (time/space).

2 Exemplify and implement stack, queue and PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


list ADT, tree and graph to manage the
memory using static and dynamic
allocations.

3 Implement binary search tree to design PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


applications like expression trees.

4 Identify, model, solve and develop code for PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


real life problems like shortest path and MST
using graph theory.

5 Develop and compare the comparison- PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


based search algorithms and sorting
Algorithms.

6 Identify appropriate data structure and PO1,PO2,PO3,PO4,PO5,PO6,PO11,PO12


algorithm for a given contextual problem and
develop in C.
Data Structures Using C Lab (KCS-351)

List of Experiments

S. N Objectives Mapping with


Course
Outcomes
1. Sorting Algorithms-Non-Recursive. CO1,CO5

2. Sorting Algorithms-Recursive CO1,CO5

3. Searching Algorithm CO1,CO5

4. Implementation of Stack using Array. CO1,CO2

5. Implementation of Queue using Array. CO1,CO2

6. Implementation of Circular Queue using Array. CO1,CO2

7. Implementation of Stack using Linked List. CO1,CO2

8. Implementation of Queue using Linked List. CO1,CO2

9. Implementation of Circular Queue using Linked List. CO1,CO2

10. Implementation of Tree Structures, Binary Tree, Tree CO1,CO3


Traversal, Binary Search Tree, Insertion and Deletion in
BST.

11. Graph Implementation, BFS, DFS, Minimum cost spanning CO1,CO4


tree, shortest path algorithm

Experiments beyond Syllabus

S. N Objectives Mapping with


Course
Outcomes
1. Write a C program for implementing Knuth-Morris- Pratt CO6
pattern matching algorithm.

2. Write a C Program to check whether two given lists are CO6


containing the same data.
Experiment :1
Objectives: Arrange the list of numbers in ascending order using Bubble Sort.
#include<stdio.h>
#include<conio.h>
void Bubblesort(int[],int);
void main()
{
int x[20],i,n;
clrscr();
printf("\n Enter the no of element to be sorted:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
Bubblesort(x,n);
printf("\n The sorted array is:\n");
for(i=0;i<n;i++)
printf("%4d",x[i]);
getch();
}
void Bubblesort(int a[],int n)
{
int temp,pass,i;
for(pass=0;pass<n-1;pass++)
{
for(i=0;i<n-pass-1;i++)
{
if(a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
}
}
}
Output:
Objective: Arrange the list of numbers in ascending order using Insertion Sort.
#include<stdio.h>
#include<conio.h>
void Insertionsort(int[],int);
void main()
{
int x[20],i,n;
clrscr();
printf("\n Enter the no of element to be sorted:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
Insertionsort(x,n);
printf("\n The sorted array is:\n");
for(i=0;i<n;i++)
printf("%4d",x[i]);
getch();
}
void Insertionsort(int a[],int n)
{
int i,j,key;
for(j=1;j<n;j++)
{
key=a[j];
i=j-1;
while((i>-1)&&(a[i]>key))
{
a[i+1]=a[i];
i=i-1;
}
a[i+1]=key;
}
}
Output:

Objective: Arrange the list of numbers in ascending order using Selection Sort.
#include<stdio.h>
#include<conio.h>
void Selectionsort(int[],int);
void main()
{
int x[20],i,n;
clrscr();
printf("\n Enter the no of element to be sorted:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
Selectionsort(x,n);
printf("\n The sorted array is:\n");
for(i=0;i<n;i++)
printf("%4d",x[i]);
getch();
}
void Selectionsort(int a[],int n)
{
int i,j,pos,large;
for(i=n-1;i>0;i--)
{
large=a[0];
pos=0;
for(j=1;j<=i;j++)
{
if (a[i]>large)
{
large=a[j];
pos=j;
}
}
a[pos]=a[i];
a[i]=large;
}
}
OUTPUT:
Experiment 2:

Objective: Arrange the list of numbers in ascending order using Merge Sort.
#include<stdio.h>
#include<conio.h>
void Mergesort(int[],int,int);
void Merge(int[],int,int,int);
void main()
{
int x[20],i,n;
clrscr();
printf("\n Enter the no of element to be sorted:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
Mergesort(x,0,n-1);
printf("\n The sorted array is:\n");
for(i=0;i<n;i++)
printf("%4d",x[i]);
getch();
} void Mergesort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=(p+r)/2;
Mergesort(a,p,q);
Mergesort(a,q+1,r);
Merge(a,p,q,r);
}
}
void Merge(int a[], int p, int q,int r)
{
int b[20],l1,r1,i;
l1=p;
r1=q+1;
i=p;
while((l1<=q)&&(r1<=r))
{
if(a[l1]<a[r1])
{
b[i]=a[l1];
l1=l1+1;
i=i+1;
}
else
{
b[i]=a[r1];
r1=r1+1;
i=i+1;
}
}
while(l1<=q)
{
b[i]=a[l1];
l1=l1+1;
i=i+1;
}
while(r1<=r)
{
b[i]=a[r1];
r1=r1+1;
i=i+1;
}
for(i=p;i<=r;i++)
a[i]=b[i];
}
OUTPUT:

Objective: Arrange the list of numbers in ascending order using Quick Sort.
#include<stdio.h>
#include<conio.h>
void Quicksort(int[],int,int);
int partition(int[],int,int);
void main()
{
int x[20],i,n;
clrscr();
printf("\n Enter the no of element to be sorted:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
Quicksort(x,0,n-1); printf("\n The sorted array is:\n");
for(i=0;i<n;i++)
printf("%4d",x[i]);
getch();
}
void Quicksort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=Partition(a,p,r);
Quicksort(a,p,q);
Quicksort(a,q+1,r);
}
}
int Partition(int a[], int p,int r)
{
int k,i,j,temp;
k=a[p];
i=p-1;
j=r+1;
while(1)
{
do
{
j=j-1;
}while(a[j]>k);
do
{
i=i+1;
}while(a[i]<k);
if(i<j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
else
return(j);
}
}
OUTPUT:
Experiment 3:
Objective: Implementation of binary search tree using array.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define TRUE 1
#define TREENODES 100
#define FALSE 0
struct tree
{
int info;
int used;
};
struct tree node[TREENODES];
void Createtree();
void Insert(int);
void Display();
void Setleft(int,int);
void Setright(int,int);
void main()
{
int x;
char ch='1';
clrscr();
printf("\n Enter root node value:");
scanf("%d", &x);
Createtree(x);
while(ch!='3')
{
printf("\n1-INSERT");
printf("\n2-DISPLAY");
printf("\n3-QUIT");
printf("\n Enter your choice:");
fflush(stdin);
ch=getchar();
switch(ch)
{
case '1' :
printf("\n Enter the element to be inserted:");
scanf("%d",&x);
Insert(x);
break;
case '2':
Display();
break; case '3':
break;
default:
printf("\n Wrong choice!Try again:");
}
}
}
void Createtree(int x)
{
int i;
node[0].info=x;
node[0].used=TRUE;
for(i=1;i<TREENODES;i++)
node[i].used=FALSE;
}
void Insert(int x)
{
int p,q;
p=q=0;
while(q<TREENODES && node[q].used && x!=node[p].info)
{
p=q;
if(x<node[p].info)
q=2*p+1;
else
q=2*p+2;
}
if(x==node[p].info)
printf("\n %d is a duplicate number\n",x);
else
if(x<node[p].info)
Setleft(p,x);
else
Setright(p,x);
}
void Setleft(int pos,int x)
{
int q;
q=2*pos+1;
if(q>TREENODES)
printf("\n Array overflow.");
else
if(node[q].used==TRUE)
printf("\n Invalid insertion.");
else
{
node[q].info=x;

node[q].used=TRUE;
}
}
void Setright(int pos,int x)
{
int q;
q=2*pos+2;
if(q>TREENODES)
printf("\n Array overflow.");
else
if(node[q].used==TRUE)
printf("\n Invalid insertion.\n");
else
{
node[q].info=x;
node[q].used=TRUE;
}
}
void Display()
{
int i;
for(i=0;i<TREENODES;i++)
if(node[i].used==TRUE)
printf("%d ",node[i].info);
printf("\n");
}
Output:
Objective: To Search an element using sequential search.
#include<stdio.h>
#include<conio.h>
int Sequentialsearch(int[],int,int);
void main()
{
int x[20],i,n,p,key;
clrscr();
printf("\n Enter the no of element:");
scanf("%d",&n);
printf("\n Enter %d elements:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
printf("\n Enter the element to be search:");
scanf("%d",&key);
p=Sequentialsearch(x,n,key);
if(p==-1)
printf("\n The searchis unsuccessful:\n");
else
printf("\n%d is found at location %d",key,p);
getch();
}
int Sequentialsearch(int a[],int n ,int k)
{
int i;
for(i=0;i<n;i++)
{
if(k==a[i])
return(i);
}
return(-1);
}
Output:

Objective: To Search an element using binary search.


#include<stdio.h>
#include<conio.h>
int Binarysearch(int[],int,int);
void main()
{
int x[20],i,n,p,key;
clrscr();
printf("\n Enter the no of element:");
scanf("%d",&n);
printf("\n Enter %d elements in assending order:",n);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
printf("\n Enter the element to be search:");
scanf("%d",&key);
p=Binarysearch(x,n,key);
if(p==-1)
printf("\n The searchis unsuccessful:\n");
else
printf("\n%d is found at location %d",key,p);

getch();
}
int Binarysearch(int a[],int n ,int k)
{
int lo,hi,mid;
lo=0;
hi=n-1;
while(lo<=hi)
{
mid=(lo+hi)/2;
if(k==a[mid])
return(mid);
if(k<a[mid])
hi=mid-1;
else
lo=mid+1;
}
return(-1);
}
Output:
Experiment 4:
Objective: Implementation of stack using array.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXSTK 100
int top=-1;
int items[MAXSTK];
int Isempty();
int Isfull();
void Push(int);
int Pop();
void Display();
void main()
{
int x;
char ch='1';
clrscr();
while(ch!='4')
{
printf("\n 1-PUSH");

printf("\n 2-POP");
printf("\n 3-DISPLAY");
printf("\n 4-QUIT");
printf("\n Enter your choice:");
fflush(stdin);
ch=getchar();
switch(ch)
{
case '1':
printf("\n Enter the element to be pushed:");
scanf("%d",&x);
Push(x);
break;
case '2':
x=Pop();
printf("\n Pop element is %d\n:",x);
break;
case '3':
Display();
break;
case '4':
break;
default:
printf("\n Wrong choice!Try again:");
}
}
}
int Isempty()
{
if(top==-1)
return 1;
else
return 0;
}
int Isfull()
{
if(top==MAXSTK-1)
return 1;
else
return 0;
}
void Push(int x)
{
if(Isfull())
{
printf("\n Stack full");
return;

}
top++;
items[top]=x;
}
int Pop()
{
int x;
if(Isempty())
{
printf("\n Stack empty");
exit(0);
}
x=items[top];
top--;
return x;
}
void Display()
{
int i;
if(Isempty())
{
printf("\n Stack empty");
return;
}
printf("\n Elements in the Stack are :\n");
for(i=top;i>=0;i--)
printf("%d\n",items[i]);
}
Output:
Experiment 5:
Objective: Implementation of queue using array.
How Queues work?

You can think of queues as a queue of people at airport ticket counter. The first person to enter the queue is served by the air

hostess at ticket counter first, the last person to enter is served last. Which is why Queues are called as First in First out

(FIFO) system or Last in Last out system(LILO)

The following are terminologies used in Queue Array implementation –

• Front – The item at the front of the queue is called front item

• Rear – The item at the end of the Queue is called rear item

• Enqueue – Process of adding or inserting a new item in the queue is called as Enqueing

• Dequeueing – Process of removing or deleting an existing item from the queue is called as dequeueing

• Size – The max size of the queue is called as size an is initialised when the queue is created

• currSize – The size of queue at any given time is notated as currSize.

C Program to Implement Queues using Arrays


#include<stdio.h>
#define SIZE 5
//Basic value initialisation
int queue[SIZE], front = -1, rear = -1;

//Function created to handle enqueue


void enqueue(int item){
if(rear == SIZE-1){
printf("Can't enqueue as the queue is full\n");
}
else{
//The first element condition
if(front == -1){
front = 0;
}

rear = rear + 1;
queue[rear] = item;
printf("We have enqueued %d\n",item);
}
}

//Function created to handle dequeue


void dequeue(){
if(front == -1){
printf("Can't dequeue as the queue is empty\n");
}
else{
printf("We have dequeued : %d\n", queue[front]);
front = front + 1;

//Only happens when the last element was dequeued


if(front > rear){
front = -1;
rear = -1;
}
}
}

//function to print the queue


void printQueue(){
if(rear == -1)
printf("\nUnable to display as queue is empty");
else{
int i;
printf("\nThe queue after enqueue & dequeue ops looks like :");

for(i = front; i <= rear; i++)


printf("%d ",queue[i]);
}
}

int main()
{
//enqueue begins here
enqueue(2);
enqueue(4);
enqueue(6);
enqueue(8);

//dequeue beings here


dequeue();
dequeue();

printQueue();
return 0;
}
Output –
We have enqueued 2
We have enqueued 4
We have enqueued 6
We have enqueued 8

We have dequeued : 2
We have dequeued : 4

The queue after enqueue & dequeue ops looks like :6 8


Problem with simple implementation of Queue using Arrays

The simple implementation of queues faces a unique problem

• Whenever we do simultaneous enqueue or dequeue in the queue.

• The effective size of queue is reduced

• This can be solved once all the elements are dequeued and values of front and rear are again put back to -1.

Alternative wayAnother way of solving this is either by circular queues or tweak in implementation as given in the
code below -×Dismiss alert

The above is solved by using remainder operations as %(maxCapacity)


Code
#include<stdio.h>
#define maxCapacity 5

int queue[maxCapacity], front = -1, rear = -1, currSize = 0;

void enQueue(int data){


if(currSize == maxCapacity)
printf("\nMax Size reached can't do enqueue");
else{
if(front == -1){
front = currSize = 0;
rear = maxCapacity - 1;
}

//imagine scenario where enqueue is happening at last element of queue


//if some dequeue has happened then 0th element or others may be free
//using % operation we can now enter at 0th or others positions here
rear = (rear + 1)%maxCapacity;
queue[rear] = data;
currSize = currSize + 1;
printf("%d Successfully Enqueued at array pos:%d\n", data,rear);
}
}
void deQueue(){
if(currSize == 0)
printf("\nNo elements, queue is empty can't dequeue");
else{
printf("\nDequeued : %d", queue[front]);

int item = queue[front];


front = (front + 1)%maxCapacity;
currSize = currSize - 1;

printf("\n%d Successfully dequeued & changed front value which is: at pos:%d\n", item,front);
}
}
void display(){
if(rear == -1)
printf("\nQueue was Empty!!!");
else{
int i;
printf("\nQueue :\n");

for(i=front; i<=rear; i++)


printf("%d ",queue[i]);
}
}

int main()
{
enQueue(2);//front: a[0], rear: a[0]
enQueue(4);//front: a[0], rear: a[1]
enQueue(6);//front: a[0], rear: a[2]
enQueue(8);//front: a[0], rear: a[3]

//front: a[0], rear: a[3]


deQueue();//0th pos now empty, //front: a[1], rear: a[3]
deQueue();//1st pos now empty, //front: a[2], rear: a[3]

//note the explanation in the above image starts from here

enQueue(10);//front: a[2], rear: a[4]

//front: a[2], rear: a[4]

//rear = (rear + 1)%maxCapacity; a[rear] = data;


//rear = (4 + 1)%maxCapacity; i.e. rear = 5%5 = 0, thus, a[0] = 12;
enQueue(12);//front: a[2], rear: a[0]
enQueue(14);//front: a[2], rear: a[1]

deQueue();//2nd pos now empty, front: a[3], rear: a[1]

enQueue(14);//front: a[3], rear: a[2]

return 0;
}
Output
2 Successfully Enqueued at array pos:0
4 Successfully Enqueued at array pos:1
6 Successfully Enqueued at array pos:2
8 Successfully Enqueued at array pos:3

Dequeued : 2
2 Successfully dequeued and changed front value which is: at pos:1

Dequeued : 4
4 Successfully dequeued & changed front value which is: at pos:2

10 Successfully Enqueued at array pos:4


12 Successfully Enqueued at array pos:0
14 Successfully Enqueued at array pos:1

Dequeued : 6
6 Successfully dequeued & changed front value which is: at pos:3
14 Successfully Enqueued at array pos:2
Experiment 6:
Objective: Implementation of circular queue using array.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXQ 100
int front=-1,rear=-1;
int items[MAXQ];
int Isempty();
int Isfull();
void Insert(int);
int Delete();
void Display();
void main()
{
int x;
char ch='1';
clrscr();
while(ch!='4')

{
printf("\n 1-INSERT");
printf("\n 2-DELETE");
printf("\n 3-DISPLAY");
printf("\n 4-QUIT");
printf("\n Enter your choice:");
fflush(stdin);
ch=getchar();
switch(ch)
{
case '1':
printf("\n Enter the nos of element to be inserted:");
scanf("%d",&x);
Insert(x);
break;
case '2':
x=Delete();
printf("\n Deleted element is %d\n:",x);
break;
case '3':
Display();
break;
case '4':
break;
default:
printf("\n Wrong choice!Try again:");
}
}
getch();
}
int Isempty()
{
if(front==-1)
return 1;
else
return 0;
}
int Isfull()
{
if(front==(rear+1)%MAXQ)
return 1;
else
return 0;
}
void Insert(int x)
{

if(Isfull())

{
printf("\n Queue full");
return;
}
if (front==-1)
{
front=0;
rear=0;
}
else
rear=(rear+1)%MAXQ;
items[rear]=x;
}
int Delete()
{
int x;
if(Isempty())
{
printf("\n Queue is empty");
exit(0);
}
x=items[front];
if (front==rear)
{
front=-1;
rear=-1;
}
else
front=(front+1)%MAXQ;
return x;
}
void Display()
{
int i,n;
if(Isempty())
{
printf("\n Queue is empty");
return;
}
printf("\n Elements in the Queue are :\n");
if(front<=rear)
{
for(i=front;i<=rear;i++)
printf("%d\n",items[i]);
}
else
{

for(i=front;i<=MAXQ-1;i++)
printf("%d\n",items[i]);
for(i=0;i<=rear;i++)
printf("%d\n",items[i]);
}
}
Output:
Experiment 7:
OBJECTIVE: Write a C program to implement stack using linked list.

SOURCE CODE
#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*top,*top1,*temp;
int topelement();
void push(int data);
void pop();
void empty();
void display();
void destroy();
void stack_count();
void create();
int count = 0;
void main()
{
int no, ch, e;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Top");
printf("\n 4 - Empty");
printf("\n 5 - Exit");
printf("\n 6 - Dipslay");
printf("\n 7 - Stack Count");
printf("\n 8 - Destroy stack");
create();
while (1)
{
printf("\n Enter choice : ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf("%d", &no);
push(no);
break;
case 2:
pop();
break;
case 3:
if (top == NULL)
printf("No elements in stack");
else
{
e = topelement();
printf("\n Top element : %d", e);
}
break;
case 4:
empty();
break;
case 5:
exit(0);
case 6:
display();
break;
case 7:
stack_count();
break;
case 8:
destroy();
break;
default :
printf(" Wrong choice, Please enter correct choice ");
break;
}
}
}
/* Create empty stack */
void create()
{
top = NULL;
}
/* Count stack elements */
void stack_count()
{
printf("\n No. of elements in stack : %d", count);
}
/* Push data into stack */
void push(int data)
{
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
top->info = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
temp->info = data;
top = temp;
}
count++;
}
/* Display stack elements */
void display()
{
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%d ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop()
{
top1 = top;
if (top1 == NULL)
{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %d", top->info);
free(top);
top = top1;
count--;
}
/* Return top element */
int topelement()
{
return(top->info);
}
/* Check if stack is empty or not */
void empty()
{
if (top == NULL)
printf("\n Stack is empty");
else
printf("\n Stack is not empty with %d elements", count);
}
/* Destroy entire stack */
void destroy()
{
top1 = top; 61
while (top1 != NULL)
{
top1 = top->ptr;
free(top);
top = top1;
top1 = top1->ptr;
}
free(top1);
top = NULL;
printf("\n All stack elements destroyed");
count = 0;
}
INPUT/OUTPUT:
1 - Push
2 - Pop
3 - Top
4 - Empty
5 - Exit
6 - Dipslay
7 - Stack Count
8 - Destroy stack
Enter choice : 1
Enter data : 56
Enter choice : 1
Enter data : 80
Enter choice : 2
Popped value : 80
Enter choice : 3
Top element : 56
Enter choice : 1
Enter data : 78
Enter choice : 1
Enter data : 90
Enter choice : 6
90 78 56
Enter choice : 7
No. of elements in stack : 3
Enter choice : 8
All stack elements destroyed
Enter choice : 4
Stack is empty
Enter choice : 5
Experiment 8:
Objective: Implementation of Queue using Linked List.

Introduction: Implementation of Queues using Linked List in C solves the problem of Queue
implementation with arrays as using linked list for implementing queue we need not to define the
size of the queue and it can work on the infinite number of values.Implementing queue using linked
list will not change its behavior i.e. the queue will continue to work with FIFO architecture.
Steps for implementing queue using linked list
enqueue(data)

• Build a new node with given data.


• Check if the queue is empty or not.
• If queue is empty then assign new node to front and rear.
• Else make next of rear as new node and rear as new node.

dequeue()

• Check if queue is empty or not.


• If queue is empty then dequeue is not possible.
• Else store front in temp
• And make next of front as front.

print()

• Check if there is some data in the queue or not.


• If the queue is empty print “No data in the queue.”
• Else define a node pointer and initialize it with front.
• Print data of node pointer until the next of node pointer becomes NULL.
Algorithm for implementing queue using linked list
enqueue(int d)

• STRUCT NODE* NEW_N


• NEW_N->DATA = D
• NEW_N->NEXT = NULL
• IF((FRONT == NULL)&&(REAR == NULL))
• FRONT = REAR = NEW_N
• ELSE
• REAR->NEXT = NEW_N
• REAR = NEW_N

dequeue()

• STRUCT NODE *TEMP


• TEMP = FRONT
• IF((FRONT == NULL)&&(REAR == NULL))
• RETURN
• ELSE
• FRONT = FRONT->NEXT
• FREE(TEMP)

print()

• STRUCT NODE* TEMP


• IF((FRONT == NULL)&&(REAR == NULL))
• RETURN
• ELSE
• TEMP = FRONT
• WHILE(TEMP)
• RETURN TEMP->DATA
• TEMP = TEMP->NEXT

Code for implementing queue using linked list in C


#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};//defining linked list to implement queue
struct node *front = NULL;
struct node *rear = NULL;
void enqueue(int d)//function to insert a node in queue
{
struct node* new_n;
new_n = (struct node*)malloc(sizeof(struct node));
new_n->data = d;
new_n->next = NULL;
if((front == NULL)&&(rear == NULL)){
front = rear = new_n;
}
else{
rear->next = new_n;
rear = new_n;
}

}
void print()//function to display the queue
{
struct node* temp;
if((front == NULL)&&(rear == NULL)){
printf("\nQueue is Empty");
}
else{
temp = front;
while(temp){
printf("\n%d",temp->data);
temp = temp->next;
}
}
}
void dequeue()//function to delete an element from a queue
{
struct node *temp;
temp = front;
if((front == NULL)&&(rear == NULL)){
printf("\nQueue is Empty");
}
else{
front = front->next;
free(temp);
}
}
int main()//main function to use all our declared function
{
int opt,n,i,data;
printf("Enter Your Choice:-");
while(opt!=0){
printf("\n\n1 for Insert the Data in Queue\n2 for show the Data in Queue
\n3 for Delete the data from the Queue\n0 for Exit");
scanf("%d",&opt);
switch(opt){
case 1:
printf("\nEnter the size: ");
scanf("%d",&n);
printf("\nEnter your data\n");
i=0;
while(i<n){
scanf("%d",&data);
enqueue(data);
i++;
}
break;
case 2:
print();
break;
case 3:
dequeue();
break;
case 0:
break;
default:
printf("\nIncorrect Choice");

}
}
}
Output:
Enter Your Choice:-

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit
1

Enter the size: 3

Enter your data


12
24
36

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit
3

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit
2

24
36

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit
0

Time Complexity: Time complexity of both operations enqueue() and dequeue() is O(1) as we only change
few pointers in both operations. There is no loop in any of the operations.
Experiment 9:
Objective: Implementation of Circular Queue using Linked List.
Introduction: Using Circular Queue is better than normal queue because there is no memory
wastage. Linked list provide the facility of dynamic memory allocation so it is easy to
create. When we implement circular Queue using linked list it is similar to circular linked list
except there is two pointer front and rear in circular Queue where as circular linked list has
only one pointer head. Lets see how to implement Circular Queue using Linked list in C
Programming.
Steps for Implementing Circular Queue using Linked List in C
enqueue(data)

• Create a struct node type node.


• Insert the given data in the new node data section and NULL in address section.
• If Queue is empty then initialize front and rear from new node.
• Queue is not empty then initialize rear next and rear from new node.
• New node next initialize from front

dequeue()

• Check if queue is empty or not.


• If queue is empty then dequeue is not possible.
• Else Initialize temp from front.
• If front is equal to the rear then initialize front and rear from null.
• Print data of temp and free temp memory.
• If there is more than one node in Queue then make front next to front then initialize rear next from front.
• Print temp and free temp.

print()

• Check if there is some data in the queue or not.


• If the queue is empty print “No data in the queue.”
• Else define a node pointer and initialize it with front.
• Print data of node pointer until the next of node pointer becomes NULL.
Algorithm for Implementing Circular Queue using linked list in C
enqueue(int d)

• Create a new node of structure node type.


• New_node->data = entered data.
• New_node->Next = NULL.
• IF(Front == NULL)
• THEN
• Front = Rear = New_node
• Rear->Next = Front
• END IF
• Front = New_node.
• End IF.
• ELSE
• Rear->Next = New_node
• Rear = New_node
• New_node->Next = Front
• End ELSE
dequeue()

• Create a temporary pointer temp of node structure type


• IF(Front == NULL)
• Print ‘Underflow Condition’
• End IF
• ELSE IF(Front == Rear)
• Front = Rear = NULL
• Free(temp)
• End ELSE IF
• ELSE
• Front = Front->Next
• Rear->Next = Front
• Free(temp)

print()

• STRUCT NODE* TEMP


• IF((FRONT == NULL)&&(REAR == NULL))
• RETURN
• ELSE
• TEMP = FRONT
• WHILE(TEMP)
• RETURN TEMP->DATA
• TEMP = TEMP->NEXT

C Program to Implement Circular Queue using Linked list


#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node* next;
};
struct node *f = NULL;
struct node *r = NULL;
void enqueue(int d) //Insert elements in Queue
{
struct node* n;
n = (struct node*)malloc(sizeof(struct node));
n->data = d;
n->next = NULL;
if((r==NULL)&&(f==NULL))
{
f = r = n;
r->next = f;
}
else
{
r->next = n;
r = n;
n->next = f;
}
}
void dequeue() // Delete an element from Queue
{
struct node* t;
t = f;
if((f==NULL)&&(r==NULL))
printf("\nQueue is Empty");
else if(f == r){
f = r = NULL;
free(t);
}
else{
f = f->next;
r->next = f;
free(t);
}

}
void print(){ // Print the elements of Queue
struct node* t;
t = f;
if((f==NULL)&&(r==NULL))
printf("\nQueue is Empty");
else{
do{
printf("\n%d",t->data);
t = t->next;
}while(t != f);
}
}
int main()
{
int opt,n,i,data;
printf("Enter Your Choice:-");
do{
printf("\n\n1 for Insert the Data in Queue\n2 for show the Data in Queue
\n3 for Delete the data from the Queue\n0 for Exit");
scanf("%d",&opt);
switch(opt){
case 1:
printf("\nEnter the number of data");
scanf("%d",&n);
printf("\nEnter your data");
i=0;
while(i<n){
scanf("%d",&data);
enqueue(data);
i++;
}
break;
case 2:
print();
break;
case 3:
dequeue();
break;
case 0:
break;
default:
printf("\nIncorrect Choice");

}
}while(opt!=0);
return 0;
}
Enter the number of data 5

Enter your data


34
33
22
76
32

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit 3

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit 2

33
22
76
32

1 for Insert the Data in Queue


2 for show the Data in Queue
3 for Delete the data from the Queue
0 for Exit
Experiment No:10
Objective: Implementation of Tree Structures, Binary Tree, Tree Traversal, Binary Search Tree,
Insertion and Deletion in BST.

Explanation: In this program, we need to create a binary search tree, delete a node from the tree, and display
the nodes of the tree by traversing the tree using in-order traversal. In in-order traversal, for a given node, first, we
traverse the left child then root then right child (Left -> Root -> Right).

In Binary Search Tree, all nodes which are present to the left of root will be less than root node and nodes which are
present to the right will be greater than the root node.

Insertion:
a. If the value of the new node is less than the root node then, it will be inserted to the left subtree.

b. If the value of the new node is greater than root node then, it will be inserted to the right subtree.

Deletion:
a. If the node to be deleted is a leaf node then, parent of that node will point to null. For eg. If we delete 90, then
parent node 70 will point to null.

b. If the node to be deleted has one child node, then child node will become a child node of the parent node. For
eg. If we delete 30, then node 10 which was left child of 30 will become left child of 50.

c. If the node to be deleted has two children then, we find the node(minNode) with minimum value from the right
subtree of that current node. The current node will be replaced by its successor(minNode).

Algorithm
1. Define Node class which has three attributes namely: data, left and right. Here, left represents the left child of
the node and right represents the right child of the node.

2. When a node is created, data will pass to the data attribute of the node and both left and right will be set to null.

3. Define another class which has an attribute root.

a. Root represents the root node of the tree and initializes it to null.

insert() will insert the new value into a binary search tree:

. It checks whether root is null, which means tree is empty. New node will become root node of tree.

a. If tree is not empty, it will compare value of new node with root node. If value of new node is greater
than root, new node will be inserted to right subtree. Else, it will be inserted in left subtree.

deleteNode() will delete a particular node from the tree:


. If value of node to be deleted is less than root node, search node in left subtree. Else, search in right subtree.

a. If node is found and it has no children, then set the node to null.

b. If node has one child then, child node will take position of node.

c. If node has two children then, find a minimum value node from its right subtree. This minimum value
node will replace the current node.

Solution
1. include <stdio.h>
2. #include <stdlib.h>
3. #include <stdbool.h>
4.
5. //Represent a node of binary tree
6. struct node{
7. int data;
8. struct node *left;
9. struct node *right;
10. };
11.
12. //Represent the root of binary tree
13. struct node *root= NULL;
14.
15. //createNode() will create a new node
16. struct node* createNode(int data){
17. //Create a new node
18. struct node *newNode = (struct node*)malloc(sizeof(struct node));
19. //Assign data to newNode, set left and right children to NULL
20. newNode->data= data;
21. newNode->left = NULL;
22. newNode->right = NULL;
23.
24. return newNode;
25. }
26.
27. //insert() will add new node to the binary search tree
28. void insert(int data) {
29. //Create a new node
30. struct node *newNode = createNode(data);
31.
32. //Check whether tree is empty
33. if(root == NULL){
34. root = newNode;
35. return;
36. }
37. else {
38. //current node point to root of the tree
39. struct node *current = root, *parent = NULL;
40.
41. while(true) {
42. //parent keep track of the parent node of current node.
43. parent = current;
44.
45. //If data is less than current's data, node will be inserted to the left of tree
46. if(data < current->data) {
47. current = current->left;
48. if(current == NULL) {
49. parent->left = newNode;
50. return;
51. }
52. }
53. //If data is greater than current's data, node will be inserted to the right of tree
54. else {
55. current = current->right;
56. if(current == NULL) {
57. parent->right = newNode;
58. return;
59. }
60. }
61. }
62. }
63. }
64.
65. //minNode() will find out the minimum node
66. struct node* minNode(struct node *root) {
67. if (root->left != NULL)
68. return minNode(root->left);
69. else
70. return root;
71. }
72.
73. //deleteNode() will delete the given node from the binary search tree
74. struct node* deleteNode(struct node *node, int value) {
75. if(node == NULL){
76. return NULL;
77. }
78. else {
79. //value is less than node's data then, search the value in left subtree
80. if(value < node->data)
81. node->left = deleteNode(node->left, value);
82.
83. //value is greater than node's data then, search the value in right subtree
84. else if(value > node->data)
85. node->right = deleteNode(node->right, value);
86.
87. //If value is equal to node's data that is, we have found the node to be deleted
88. else {
89. //If node to be deleted has no child then, set the node to NULL
90. if(node->left == NULL && node->right == NULL)
91. node = NULL;
92.
93. //If node to be deleted has only one right child
94. else if(node->left == NULL) {
95. node = node->right;
96. }
97.
98. //If node to be deleted has only one left child
99. else if(node->right == NULL) {
100. node = node->left;
101. }
102.
103. //If node to be deleted has two children node
104. else {
105. //then find the minimum node from right subtree
106. struct node *temp = minNode(node->right);
107. //Exchange the data between node and temp
108. node->data = temp->data;
109. //Delete the node duplicate node from right subtree
110. node->right = deleteNode(node->right, temp->data);
111. }
112. }
113. return node;
114. }
115. }
116.
117. //inorder() will perform inorder traversal on binary search tree
118. void inorderTraversal(struct node *node) {
119.
120. //Check whether tree is empty
121. if(root == NULL){
122. printf("Tree is empty\n");
123. return;
124. }
125. else {
126.
127. if(node->left!= NULL)
128. inorderTraversal(node->left);
129. printf("%d ", node->data);
130. if(node->right!= NULL)
131. inorderTraversal(node->right);
132.
133. }
134. }
135.
136. int main()
137. {
138. //Add nodes to the binary tree
139. insert(50);
140. insert(30);
141. insert(70);
142. insert(60);
143. insert(10);
144. insert(90);
145.
146. printf("Binary search tree after insertion: \n");
147. //Displays the binary tree
148. inorderTraversal(root);
149.
150. struct node *deletedNode = NULL;
151. //Deletes node 90 which has no child
152. deletedNode = deleteNode(root, 90);
153. printf("\nBinary search tree after deleting node 90: \n");
154. inorderTraversal(root);
155.
156. //Deletes node 30 which has one child
157. deletedNode = deleteNode(root, 30);
158. printf("\nBinary search tree after deleting node 30: \n");
159. inorderTraversal(root);
160.
161. //Deletes node 50 which has two children
162. deletedNode = deleteNode(root, 50);
163. printf("\nBinary search tree after deleting node 50: \n");
164. inorderTraversal(root);
165.
166. return 0;
167. }

Output:

Binary search tree after insertion:


10 30 50 60 70 90
Binary search tree after deleting node 90:
10 30 50 60 70
Binary search tree after deleting node 30:
10 50 60 70
Binary search tree after deleting node 50:
10 60 70
Experiment No :11
Objective: Graph Implementation, BFS, DFS, Minimum cost spanning tree, shortest path
algorithm

Explanation: BFS algorithm


A standard BFS implementation puts each vertex of the graph into one of two categories:

1. Visited

2. Not Visited

The purpose of the algorithm is to mark each vertex as visited while avoiding cycles.

The algorithm works as follows:

1. Start by putting any one of the graph's vertices at the back of a queue.

2. Take the front item of the queue and add it to the visited list.

3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the visited list to the back of the
queue.

4. Keep repeating steps 2 and 3 until the queue is empty.

The graph might have two different disconnected parts so to make sure that we cover every vertex, we can
also run the BFS algorithm on every node

BFS example
Let's see how the Breadth First Search algorithm works with an example. We use an undirected graph with
5 vertices.
We start from vertex 0, the BFS algorithm starts by putting it in the Visited list and putting all its adjacent
vertices in the stack

Next, we visit the element at the front of queue i.e. 1 and go to its adjacent nodes. Since 0 has already
been visited, we visit 2 instead.

Visit the first neighbour of start node 0, which is 1


Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the back of the queue and visit 3, which is
at the front of the queue.

4 remains in the queue


Only 4 remains in the queue since the only adjacent node of 3 i.e. 0 is already visited. We visit it.Visit last
remaining item in the stack to check if it has unvisited neighbours

Since the queue is empty, we have completed the Breadth First Traversal of the graph.
BFS pseudocode

create a queue Q

mark v as visited and put v into Q

while Q is non-empty

remove the head u of Q

mark and enqueue all (unvisited) neighbours of u

/ BFS algorithm in C

#include <stdio.h>
#include <stdlib.h>
#define SIZE 40

struct queue {
int items[SIZE];
int front;
int rear;
};

struct queue* createQueue();


void enqueue(struct queue* q, int);
int dequeue(struct queue* q);
void display(struct queue* q);
int isEmpty(struct queue* q);
void printQueue(struct queue* q);

struct node {
int vertex;
struct node* next;
};

struct node* createNode(int);

struct Graph {
int numVertices;
struct node** adjLists;
int* visited;
};

// BFS algorithm
void bfs(struct Graph* graph, int startVertex) {
struct queue* q = createQueue();

graph->visited[startVertex] = 1;
enqueue(q, startVertex);

while (!isEmpty(q)) {
printQueue(q);
int currentVertex = dequeue(q);
printf("Visited %d\n", currentVertex);

struct node* temp = graph->adjLists[currentVertex];

while (temp) {
int adjVertex = temp->vertex;
if (graph->visited[adjVertex] == 0) {
graph->visited[adjVertex] = 1;
enqueue(q, adjVertex);
}
temp = temp->next;
}
}
}

// Creating a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

// Creating a graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));


graph->visited = malloc(vertices * sizeof(int));

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}

return graph;
}

// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
struct node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

// Add edge from dest to src


newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

// Create a queue
struct queue* createQueue() {
struct queue* q = malloc(sizeof(struct queue));
q->front = -1;
q->rear = -1;
return q;
}

// Check if the queue is empty


int isEmpty(struct queue* q) {
if (q->rear == -1)
return 1;
else
return 0;
}

// Adding elements into queue


void enqueue(struct queue* q, int value) {
if (q->rear == SIZE - 1)
printf("\nQueue is Full!!");
else {
if (q->front == -1)
q->front = 0;
q->rear++;
q->items[q->rear] = value;
}
}

// Removing elements from queue


int dequeue(struct queue* q) {
int item;
if (isEmpty(q)) {
printf("Queue is empty");
item = -1;
} else {
item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
printf("Resetting queue ");
q->front = q->rear = -1;
}
}
return item;
}

// Print the queue


void printQueue(struct queue* q) {
int i = q->front;

if (isEmpty(q)) {
printf("Queue is empty");
} else {
printf("\nQueue contains \n");
for (i = q->front; i < q->rear + 1; i++) {
printf("%d ", q->items[i]);
}
}
}

int main() {
struct Graph* graph = createGraph(6);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 1, 4);
addEdge(graph, 1, 3);
addEdge(graph, 2, 4);
addEdge(graph, 3, 4);

bfs(graph, 0);

return 0;
}

BFS Algorithm Complexity


The time complexity of the BFS algorithm is represented in the form of O(V + E), where V is the number of
nodes and E is the number of edges.
The space complexity of the algorithm is O(V).

Depth First Search (DFS) :


Depth First Search Algorithm
A standard DFS implementation puts each vertex of the graph into one of two categories:

1. Visited

2. Not Visited

The purpose of the algorithm is to mark each vertex as visited while avoiding cycles.

The DFS algorithm works as follows:

1. Start by putting any one of the graph's vertices on top of a stack.

2. Take the top item of the stack and add it to the visited list.

3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the visited list to the top of the
stack.

4. Keep repeating steps 2 and 3 until the stack is empty.

Depth First Search Example


Let's see how the Depth First Search algorithm works with an example. We use an undirected graph with 5
vertices.

We start from vertex 0, the DFS algorithm starts by putting it in the Visited list and putting all its adjacent
vertices in the stack.
Next, we visit the element at the top of stack i.e. 1 and go to its adjacent nodes. Since 0 has already been
visited, we visit 2 instead.

Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of the stack and visit it.
After we visit the last element 3, it doesn't have any unvisited adjacent nodes, so we have completed the
Depth First Traversal of the graph.

DFS Pseudocode (recursive implementation)


The pseudocode for DFS is shown below. In the init() function, notice that we run the DFS function on
every node. This is because the graph might have two different disconnected parts so to make sure that
we cover every vertex, we can also run the DFS algorithm on every node.

DFS(G, u)

u.visited = true

for each v ∈ G.Adj[u]

if v.visited == false

DFS(G,v)

init() {

For each u ∈ G

u.visited = false

For each u ∈ G

DFS(G, u)
}

DFS Implementation
/ DFS algorithm in C

#include <stdio.h>
#include <stdlib.h>

struct node {
int vertex;
struct node* next;
};

struct node* createNode(int v);

struct Graph {
int numVertices;
int* visited;

// We need int** to store a two dimensional array.


// Similary, we need struct node** to store an array of Linked lists
struct node** adjLists;
};

// DFS algo
void DFS(struct Graph* graph, int vertex) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;

graph->visited[vertex] = 1;
printf("Visited %d \n", vertex);

while (temp != NULL) {


int connectedVertex = temp->vertex;

if (graph->visited[connectedVertex] == 0) {
DFS(graph, connectedVertex);
}
temp = temp->next;
}
}

// Create a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

// Create graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));

graph->visited = malloc(vertices * sizeof(int));

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}

// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
struct node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

// Add edge from dest to src


newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

// Print the graph


void printGraph(struct Graph* graph) {
int v;
for (v = 0; v < graph->numVertices; v++) {
struct node* temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp) {
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}
}

int main() {
struct Graph* graph = createGraph(4);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);

printGraph(graph);

DFS(graph, 2);

return 0;
}

Complexity of Depth First Search


The time complexity of the DFS algorithm is represented in the form of O(V + E), where V is the number of
nodes and E is the number of edges.
The space complexity of the algorithm is O(V).
Experiments beyond Syllabus
Experiment :1
Objective: Write a C program for implementing Knuth-Morris- Pratt pattern matching algorithm.

PROGRAM LOGIC
1. Read the pattern and text
2. Compute failure function
3. Apply the KMP algorithm
SOURCE CODE
Knuth-Morris- Pratt pattern matching algorithm

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void computefailure(char *pat, int M, int *f);

void KMPSearch(char *pat, char *txt) //to implement kmp search

{
int M = strlen(pat);//length of pattern
int N = strlen(txt);//length of text

int *f = (int *)malloc(sizeof(int)*M); //dynamic allocation


int j = 0; // index for pat[]

computefailure(pat, M, f);

int i = 0; // index for txt[]


while(i < N)
{
if(pat[j] == txt[i])
{
j++;
i++;
}
if (j == M)
{
printf("Found pattern at index %d \n", i-j);
j = f[j-1];
}
else if(pat[j] != txt[i])
{
if(j != 0)
j = f[j-1];
else
i = i+1;
}
}
free(f); }

void computefailure (char *pat, int M, int *f) //compute the failure function

{
int len = 0;
int i;

f[0] = 0; // f[0] is always 0


i = 1;

while(i < M)
{
if(pat[i] == pat[len])
{
len++;
f[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
if( len != 0 )
{
len = f[len-1];
}
else // if (len == 0)
{
f[i] = 0;
i++;
}
}
}
}

int main()
{
int match;
printf("\nEnter the Text: ");
gets(text); //reading the text
printf("\nEnter the Pattern: ");
gets(pattern); //reading the
pattern m=strlen(text);

n=strlen(pattern);
match=KMPSearch(pat, txt);

if(match>=0)
{
printf("\nMatch found at position %d\n\n",match);
}
else
{
printf("\nNo Match found!!!\n\n");
}
return 0;
}
PRE LAB QUESTIONS
1. what is pattern matching
2. List the various pattern matching algorithms
3. What is failure function

LAB ASSIGNMENT
1. Apply KMP algorithm on pattern “abacab” and text “abacaabaccabacabaabb”
2. Apply KMP algorithm on pattern “abaa” and text “abbbaababaab”
POST LAB QUESTIONS
1. Which pattern matching algorithm is better
2. Write the significance of Knuth-Morris- Pratt pattern matching algorithm
3. List the applications of pattern matching algorithms

INPUT AND OUTPUT


Experiment 2:

Objective: Write a C Program to check whether two given lists are containing the same data.
SOURCE CODE
#include <stdio.h>
#include <stdlib.h>
struct node
{
int num;
struct node *next;
};
void feedmember(struct node **);
int compare (struct node *, struct node *);
void release(struct node **);
int main() {
struct node *p = NULL;
struct node *q = NULL;
int result;
printf("Enter data into first list\n");
feedmember(&p);
printf("Enter data into second list\n");
feedmember(&q);
result = compare(p, q);
if (result == 1) {
printf("The 2 list are equal.\n");
}
else {
printf("The 2 lists are unequal.\n");
}
release (&p);
release (&q);
return 0;
}
int compare (struct node *p, struct node *q) {
while (p != NULL && q != NULL)
{
if (p->num != q-> num) {
return 0;
}
else
{
p = p->next;
q = q->next;
}
}
if (p != NULL || q != NULL) {
return 0;
}
else {
return 1;
}
}
void feedmember (struct node **head)
{
int c, ch;
struct node *temp;
do {
printf("Enter number: ");
scanf("%d", &c);
temp = (struct node *)malloc(sizeof(struct node));
temp->num = c;
temp->next = *head;
*head *head = temp;
printf("Do you wish to continue [1/0]: ");
scanf("%d", &ch);
}while (ch != 0);
printf("\n");
}
void release (struct node **head) {
struct node *temp = *head;
while ((*head) != NULL)
{
(*head) = (*head)->next;
free(temp);
temp = *head;
}
}
INPUT/ OUTPUT
Enter data into first list
Enter number: 12
Do you wish to continue [1/0]: 1
Enter number: 3
Do you wish to continue [1/0]: 1
Enter number: 28
Do you wish to continue [1/0]: 1
Enter number: 9
Do you wish to continue [1/0]: 0
Enter data into second list
Enter number: 12
Do you wish to continue [1/0]: 1
Enter number: 3
Do you wish to continue [1/0]: 1
Enter number: 28
Do you wish to continue [1/0]: 1
Enter number: 9
Do you wish to continue [1/0]: 0
The 2 list are equal.

You might also like