Sulthan Noushad C Assignment
Sulthan Noushad C Assignment
1) E.NO: A40105223013
For loops that iterate n times →O(n) Space complexity depends on the
For nested loops that iterate n times → datatypes and structures chosen, For eg.
O(n2) int, float char are O(1), memory allocated
variables are of O(n)
Character arrays are much more efficient compared to string style strings. The
character arrays allow direct access to individual characters and modify them from the
array. By using character arrays, you can also optimize the program by managing the
memory allocation for these data structures.
c) Differentiate between linear arrays and multidimensional arrays. Discuss their
memory representation with a diagram.
Linear Arrays Multidimensional arrays
One dimensional collection of elements Has more than one dimension
Contiguous memory allocation Contiguous memory allocation of row by
row (row-major) and column by column
(column-major)
Individual elements are accessed using Individual elements are accessed using
single index multiple indices
Can be represented as a simple line of Can be represented as a plane [2 D]or a
elements cube [3 D]
Multidimensional array
0 1 2 3
0 100 A00 104 A01 108 A02 112 A03
1 116 A10 120 A11 124 A12 128 A13
2 132 A20 136 A21 140 A22 144 A23
d) Design a system for storing and managing customer records (e.g., name, phone
number, and email) using a two-dimensional array. Include functions for adding,
searching, and deleting records. Discuss the choice of data structure.
#include <stdio.h>
#include <string.h>
char data[50][3][100];
int i;
void addrec()
{
char s[100];
char ph[100];
char e[100];
printf("\nEnter name: ");
scanf("%s",s);
printf("\nEnter phone number: ");
scanf("%s",ph);
printf("\nEnter email: ");
scanf("%s",e);
for (i=0;strlen(data[i][0])!=0 && i<50;i++);
if (i>50)
{
printf("\nArray out of bounds");
return;
}
strcpy(data[i][0],s);
strcpy(data[i][1],ph);
strcpy(data[i][2],e);
}
void disprec()
{
for (i=0;strlen(data[i][0])!=0 && i<50;i++)
{
printf("\nName: %s",data[i][0]);
printf("\nPhone number: %s",data[i][1]);
printf("\nEmail: %s",data[i][2]);
}
}
void searchrec()
{
char s[100];
printf("\nEnter name: ");
scanf("%s",s);
for (i=0;strlen(data[i][0])!=0;i++)
{
if ((strcmp(s,data[i][0]))==0)
{
printf("\nName: %s",data[i][0]);
printf("\nPhone number: %s",data[i][1]);
printf("\nEmail: %s",data[i][2]);
return;
}
}
printf("\nRecord not found");
}
void deleterec()
{
char s[100];
printf("\nEnter name: ");
scanf("%s",s);
for (i=0;strlen(data[i][0])!=0;i++)
{
if ((strcmp(s,data[i][0]))==0)
{
strcpy(data[i][0],"");
strcpy(data[i][1],"");
strcpy(data[i][2],"");
printf("\nRecord deleted");
return;
}
}
printf("\nRecord not found");
}
int main()
{
int c=1,p;
for (i=0;i<50;i++)
{
data[i][0][0]='\0';
}
while (c==1)
{
printf("\nArray program for customers ");
printf("\n1: Insert record");
printf("\n2: Search record");
printf("\n3: Display records");
printf("\n4: Delete record");
printf("\n5: Exit program");
printf("\nEnter choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
addrec();
break;
case 2:
searchrec();
break;
case 3:
disprec();
break;
case 4:
deleterec();
break;
case 5:
c=2;
break;
default:
printf("\nBad input");
break;
}
}
}
e) Apply the concept of sparse matrices to represent a chessboard with the
positions of all pieces marked. Write an algorithm to initialize, update, and display
the board state.
Pseudocode-
DEFINE BOARD_SIZE=8
DEFINE MAX_PIECES=32
STRUCT pieces
INTEGER row
INTEGER col
CHARACTER piece
FUNCTION initializeBoard()
ADD piece to board[Count] with row=0, col=0, piece= "WR"
Count++
ADD piece to board[Count] with row=0, col=7, piece= "WR"
Count++
ADD piece to board[Count] with row=0, col=1, piece= "WN"
Count++
ADD piece to board[Count] with row=0, col=6, piece= "WN"
Count++
ADD piece to board[Count] with row=0, col=2, piece= "WB"
Count++
ADD piece to board[Count] with row=0, col=5, piece= "WB"
Count++
ADD piece to board[Count] with row=0, col=3, piece= "WQ"
Count++
ADD piece to board[Count] with row=0, col=4, piece= "WK"
Count++
FOR col=0 TO 7
ADD piece to board[Count] with row=1, col=col, piece= "WP"
Count++
ADD piece to board[Count] with row=7, col=0, piece= "BR"
Count++
ADD piece to board[Count] with row=7, col=7, piece= "BR"
Count++
ADD piece to board[Count] with row=7,col=1, piece="BN"
Count++
ADD piece to board[Count] with row=7, col=6, piece="BN"
Count++
ADD piece to board[Count] with row=7, col=2, piece="BB"
Count++
ADD piece to board[Count] with row=7, col=5, piece="BB"
Count++
ADD piece to board[Count] with row=7, col=3, piece="BQ"
Count++
ADD piece to board[Count] with row=7, col=4, piece="BK"
Count++
FOR col=0 TO 7
ADD piece to board[Count] with row=6, col=col, piece="BP"
Count++
PRINT "Board initialized"
FUNCTION updatePosition(oldRow, oldCol, newRow, newCol)
FOR each piece in board
IF piece.row==oldRow AND piece.col==oldCol
piece.row=newRow
piece.col=newCol
RETURN
PRINT "Piece not found at the given position"
FUNCTION displayBoard()
DECLARE chessboard[BOARD_SIZE][BOARD_SIZE] AS CHARACTER initialized to
'_'
PRINT chessboard
MAIN
DECLARE C=1, P
WHILE C==1
SWITCH(C)
CASE 1
initializeBoard()
displayBoard
CASE 2
displayBoard()
CASE 3
updatePosition()
displayBoard
CASE 4
c=2
DEFAULT
PRINT "Bad input"
f) Analyze a scenario where a hospital stores patient records in a multidimensional array.
Write an algorithm to retrieve all patients admitted on a specific date and discuss the
efficiency of using arrays for this purpose.
Pseudocode-
DECLARE patients[MAX][3][100] AS STRING
DECLARE REQDATE AS STRING
DECLARE result[MAX][3][100] AS STRING
DECLARE count AS INTEGER
FUNCTION filterbyadm(REQDATE)
count=0
FOR i=0 TO i=MAX
IF (patients[i][2]==REQDATE)
result[count][0]=patients[i][0]
result[count][1]=patients[i][1]
result[count][2]=patients[i][2]
count++
IF count==0
PRINT "No patients admitted on this date"
RETURN
PRINT count + "patients registered on this day :-"
FOR i=0 TO count-1
PRINT "Name: "+result[i][0]
PRINT "ID: "+result[i][1]
PRINT "AdmDate: "+result[i][2]
Efficiency-
Time complexity : The time complexity of the function is O(n), We loop through all the
patients once.
Space complexity: The space complexity of the function is O(n) because we store up to
n patients in the result array.
This algorithm is efficient for small to medium sized datasets but large datasets have
better alternatives.
_________________________________________________________________________________
2)
a) Design an algorithm to insert and delete elements in a circular queue
represented using an array.
Pseudocode-
DECLARE SIZE=5
int a[SIZE],front=-1,rear=-1
FUNCTION insert(int n)
IF (rear+1)%SIZE==front
PRINT "Queue is full"
RETURN
IF front==-1
front++
rear=(rear+1)%SIZE
a[rear]=n
PRINT "Inserted "+n
FUNCTION delete()
{
IF (front==-1)
PRINT "Queue is empty"
RETURN
PRINT "Deleted "+a[front]
IF (front==rear)
front=-1
rear=-1
ELSE
front=(front+1)%SIZE
}
FUNCTION display()
{
IF front==-1
PRINT "Queue is empty"
RETURN
PRINT "Queue elements"
i=front
WHILE TRUE
PRINT a[i]
IF i==rear
BREAK
i=(i+1)%SIZE
}
b) Propose a solution for managing browser history using a stack. Implement
operations to navigate back and forward in the history. Critique the limitations of
this approach and suggest improvements.
DECLARE char forward[50], back[50], current=NULL
FUNCTION newpage(char page[50])
push(back,page)
forward=NULL
current=page
FUNCTION goback()
IF back-> EMPTY
PRINT "No pages to go back to"
ELSE
push(forward,current)
current=pop(back)
FUNCTION goforward()
IF forward-> EMPTY
PRINT "No pages to go forward to"
ELSE
push(back,current)
current=pop(forward)
FUNCTION display()
PRINT current
Critique
Memory usage- Both stacks grow in size as pages are visited and will lead to excessive
memory usage.
Navigation- This only supports linear navigation and you can’t visit a random page in
this structure.
Improvements-
• Include usage of doubly linked list which can replace stacks to allow efficient
jumping between histories.
• Include metadata and timestamps
• Introduce bookmarking to access frequently visited pages.
c) Explain and implement the process of converting infix expressions to both
postfix and prefix notations. Discuss the role of stacks in these conversions.
Infix to prefix
FUNCTION inftopref(char expression[100])
DECLARE string reverse
FOR i=LENGTH(expression)-1 TO 0
IF expression[i]=='('
APPEND ')' TO reverse
ELSE IF expression[i]==')'
APPEND ')' TO reverse
ELSE
APPEND expression[i] TO reverse
DECLARE char foperators[50];
DECLARE string result;
FOR EACH character c IN reverse
IF c IS an operand
APPEND c TO result
ELSE IF c=='('
push(operators,c)
ELSE IF c==')'
WHILE TOP(operators)!='('
APPEND TOP(operators) TO result
pop(operators)
ELSE IF c IS an operator
WHILE (operators -> NOT EMPTY) &
(precedence(c)<=precedence(TOP(operators)))
APPEND pop(operators)->result
PUSH c TO operators
WHILE operators-> NOT EMPTY
APPEND pop(operators)->result
REVERSE result
RETURN result
FUNCTION precedence(operator)
IF operator=='+' OR operator=='-'
RETURN 1
ELSE IF operator=='*' OR operator=='/'
RETURN 2
ELSE IF operator=='^'
RETURN 3
RETURN 0
Infix to postfix
FUNCTION inftopost(char expression[100])
DECLARE char operators[50]
DECLARE string result
FOR EACH character c IN expression
IF c IS an operand
APPEND c TO result
ELSE IF c=='('
PUSH (operators,c);
ELSE IF c=')'
WHILE TOP(operators)!='('
APPEND pop(operators) TO result
POP operators
ELSE IF c IS an operator
WHILE operators->NOT EMPTY &
precedence(c)>=precedence(TOP(operators))
APPEND pop(operators) TO result
PUSH c TO operators
WHILE operators->NOT EMPTY
APPEND pop(operators) TO result
RETURN result
3)
a) Construct a singly linked list to store integers. Write a function to search for a
given element and return its position.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* link;
};
struct node *first=NULL,*next=NULL,*cur=NULL,*temp=NULL;
void createnode()
{
first=(struct node*)malloc(sizeof(struct node));
temp=(struct node*)malloc(sizeof(struct node));
printf("Enter data: ");
scanf("%d",&temp->data);
first->link=temp;
printf("\nNode added");
}
void appendnode()
{
cur=(struct node*)malloc(sizeof(struct node));
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
temp=temp->link;
while(temp->link!=NULL)
{
temp=temp->link;
}
printf("\nEnter data: ");
scanf("%d",&cur->data);
temp->link=cur;
printf("\nNode appended");
}
void insertnode()
{
int pos;
int c=1;
printf("\nEnter position: ");
scanf("%d",&pos);
temp=(struct node*)malloc(sizeof(struct node));
cur=(struct node*)malloc(sizeof(struct node));
temp=first;
while((temp!=NULL) && (c<=pos))
{
if(c==pos)
{
printf("\nData: ");
scanf("%d",&cur->data);
cur->link=temp->link;
temp->link=cur;
break;
}
temp=temp->link;
c++;
}
if (c!=pos)
{
printf("\nInvalid position");
}
}
void display()
{
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
temp=temp->link;
if (temp==NULL)
{
printf("\nEmpty linked list");
}
else
{
printf("%d",temp->data);
temp=temp->link;
while(temp!=NULL)
{
printf("->%d",temp->data);
temp=temp->link;
}
}
}
void searchnode()
{
int pos=0,t=0,s;
cur=(struct node*)malloc(sizeof(struct node));
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter data to search: ");
scanf("%d",&s);
temp=temp->link;
while (temp!=NULL)
{
pos++;
if (temp->data==s)
{
printf("\nInteger found at position: %d",pos);
t=1;
break;
}
temp=temp->link;
}
if (t==0)
{
printf("\nInteger not found in linked list");
}
}
void del()
{
int s,t=0;
temp=(struct node*)malloc(sizeof(struct node));
cur=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter data to delete:");
scanf("%d",&s);
while(temp->link!=NULL)
{
cur=temp->link;
if (cur->data==s)
{
temp->link=cur->link;
printf("\nElement deleted");
t=1;
}
temp=temp->link;
}
if (t==0)
{
printf("\nInteger not found");
}
}
int main()
{
int c=1;
int p;
while (c==1)
{
printf("\nSingley linked list for integers");
printf("\n1: Create node");
printf("\n2: Insert node");
printf("\n3: Append node");
printf("\n4: Delete node");
printf("\n5: Display node");
printf("\n6: Search node");
printf("\n7: Exit the program");
printf("\nEnter the choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
appendnode();
break;
case 4:
del();
break;
case 5:
display();
break;
case 6:
searchnode();
break;
case 7:
c=2;
break;
default:
printf("\nBad input");
}
}
clrscr();
return 0;
}
b) Construct a singly linked list-based program to store and manage student
records (e.g., roll number, name, and marks). Include operations for insertion,
deletion, and searching.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int rno;
char name[100];
int marks;
struct node* link;
};
struct node *first=NULL,*next=NULL,*cur=NULL,*temp=NULL;
void createnode()
{
first=(struct node*)malloc(sizeof(struct node));
temp=(struct node*)malloc(sizeof(struct node));
printf("\nEnter roll no: ");
scanf("%d",&temp->rno);
printf("\nEnter name: ");
scanf("%s",&temp->name);
printf("\nEnter marks: ");
scanf("%d",&temp->marks);
first->link=temp;
}
void display()
{
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
temp=temp->link;
if(temp==NULL)
{
printf("\nEmpty linked list");
}
else
{
printf("\n1 \nRoll No: %d",temp->rno);
printf("\nName: %s",temp->name);
printf("\nMarks: %d",temp->marks);
printf("\n__________________\n");
temp=temp->link;
while(temp!=NULL)
{
printf("\n->\nRoll No: %d",temp->rno);
printf("\nName: %s",temp->name);
printf("\nMarks: %d",temp->marks);
temp=temp->link;
}
}
}
void insertnode()
{
int pos=0,s,t=0;
temp=(struct node*)malloc(sizeof(struct node));
cur=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter position: ");
scanf("%d",&s);
while(temp!=NULL && pos<=s )
{
pos++;
if (pos==s)
{
printf("\nEnter roll no: ");
scanf("%d",&cur->rno);
printf("\nEnter name: ");
scanf("%s",&cur->name);
printf("\nEnter marks: ");
scanf("%d",&cur->marks);
cur->link=temp->link;
temp->link=cur;
t=1;
break;
}
temp=temp->link;
}
if (t==0)
{
printf("\nInvalid position");
}
}
void del()
{
int n,t=0;
temp=(struct node*)malloc(sizeof(struct node));
cur=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter roll no: ");
scanf("%d",&n);
if (temp==NULL)
{
printf("\nEmpty linked list");
return;
}
while(temp->link!=NULL)
{
cur=temp->link;
if (cur->rno==n)
{
printf("\nRecord deleted");
temp->link=cur->link;
t=1;
break;
}
temp=temp->link;
}
if(t==0)
{
printf("\nRecord not found");
}
}
void searchnode()
{
int s,t=0;
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter roll no: ");
scanf("%d",&s);
temp=temp->link;
while(temp!=NULL)
{
if (temp->rno==s)
{
printf("\nRoll No: %d",temp->rno);
printf("\nName: %s",temp->name);
printf("\nMarks: %d",temp->marks);
t=1;
break;
}
temp=temp->link;
}
if (t==0)
{
printf("\nRoll no not found");
}
}
int main()
{
int c=1,p;
while (c==1)
{
printf("\nSingley linked list for students");
printf("\n1: Create list");
printf("\n2: Insert record");
printf("\n3: Delete record");
printf("\n4: Search record");
printf("\n5: Display record");
printf("\n6: Exit the program");
printf("\nEnter the choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
del();
break;
case 4:
searchnode();
break;
case 5:
display();
break;
case 6:
c=2;
break;
default:
printf("\nBad input");
break;
}
}
return 0;
}
c) Create a task management system using a singly linked list, where each node stores
task details (ID, description, priority). Implement functions to add, delete, and search
tasks based on priority.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
int id;
char description[100];
char priority[50];
struct node*link;
};
struct node *first=NULL,*temp,*cur;
int pval(char a[50])
{
if(strcmp(a,"high")==0)
{
return 3;
}
else if(strcmp(a,"medium")==0)
{
return 2;
}
else if(strcmp(a,"low")==0)
{
return 1;
}
return 0;
}
void createnode()
{
first=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter ID:");
scanf("%d",&temp->id);
printf("\nEnter description:");
getchar();
fgets(temp->description,sizeof(temp->description),stdin);
printf("\nEnter priority:");
fgets(temp->priority,sizeof(temp->priority),stdin);
temp->link=NULL;
}
void display()
{
temp=first;
if(temp==NULL)
{
printf("\nEmpty priority list");
return;
}
while(temp!=NULL)
{
printf("\nID:%d",temp->id);
printf("\nDescription:%s",temp->description);
printf("\nPriority:%s",temp->priority);
temp=temp->link;
}
}
void insertnode()
{
cur=(struct node*)malloc(sizeof(struct node));
printf("\nEnter id:");
scanf("%d",&cur->id);
getchar();
printf("\nEnter description:");
fgets(cur->description,sizeof(cur->description),stdin);
printf("\nEnter priority:");
fgets(cur->priority,sizeof(cur->priority),stdin);
cur->link=NULL;
if(first==NULL)
{
first=cur;
}
else
{
temp=first;
if(pval(cur->priority)>=pval(first->priority))
{
cur->link=first;
first=cur;
}
else
{
while(temp->link!=NULL&&pval(cur->priority)<pval(temp->link-
>priority))
{
temp=temp->link;
}
cur->link=temp->link;
temp->link=cur;
}
}
}
void del()
{
int id;
printf("\nEnter ID of the task to delete:");
scanf("%d",&id);
temp=first;
if(temp==NULL)
{
printf("\nEmpty priority list\n");
return;
}
if(temp->id==id)
{
first=temp->link;
return;
}
while(temp->link!=NULL&&temp->link->id!=id)
{
temp=temp->link;
}
if(temp->link==NULL)
{
printf("\nTask not found\n");
return;
}
temp->link=temp->link->link;
}
void searchtask()
{
char priority[50];
printf("\nEnter priority to search (high/medium/low):");
getchar();
fgets(priority,sizeof(priority),stdin);
temp=first;
int found=0;
while(temp!=NULL)
{
if(strcmp(temp->priority,priority)==0)
{
printf("\nID:%d",temp->id);
printf("\nDescription:%s",temp->description);
printf("\nPriority:%s",temp->priority);
found=1;
}
temp=temp->link;
}
if(!found)
{
printf("\nNo tasks found with %s priority.\n",priority);
}
}
int main()
{
int c=1,p;
while(c==1)
{
printf("\nPriority list using linked list");
printf("\n1:Create priority list");
printf("\n2:Insert tasks");
printf("\n3:Delete task");
printf("\n4:Search tasks");
printf("\n5:Display tasks");
printf("\n6:Exit program");
printf("\nEnter choice:");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
del();
break;
case 4:
searchtask();
break;
case 5:
display();
break;
case 6:
c=2;
break;
default:
printf("\nBad input\n");
break;
}
}
return 0;
}
d) Design a doubly linked list and implement operations to insert and delete a node
at a given position.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* prev;
struct node* next;
};
struct node *prev=NULL,*temp=NULL,*next=NULL,*first=NULL,*cur=NULL;
void createnode()
{
first=(struct node*)malloc(sizeof(struct node));
temp=(struct node*)malloc(sizeof(struct node));
printf("\nEnter data: ");
scanf("%d",&temp->data);
temp->prev=first;
first->next=temp;
}
void insertnode()
{
int c,pos=1;
temp=(struct node*)malloc(sizeof(struct node));
cur=(struct node*)malloc(sizeof(struct node));
temp=first;
printf("\nEnter position: ");
scanf("%d",&c);
while (temp!=NULL && pos<c)
{
temp=temp->next;
pos++;
}
if (pos!=c)
{
printf("\nInvalid position");
return;
}
printf("\nEnter data: ");
scanf("%d",&cur->data);
cur->prev=temp;
cur->next=temp->next;
temp->next=cur;
}
void del()
{
int c,pos=1;
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
if (temp==NULL)
{
printf("\nEmpty doubly linked list");
return;
}
printf("\nEnter position: ");
scanf("%d",&c);
while (temp!=NULL && pos<c)
{
pos++;
temp=temp->next;
}
if (pos!=c)
{
printf("\nInvalid position");
return;
}
cur=temp->next;
cur=cur->next;
temp->next=cur;
}
void display()
{
temp=(struct node*)malloc(sizeof(struct node));
temp=first;
if (temp==NULL)
{
printf("\nEmpty doubly linked list");
return;
}
temp=temp->next;
printf("\n%d",temp->data);
temp=temp->next;
while(temp!=NULL)
{
printf("->%d",temp->data);
temp=temp->next;
}
}
int main()
{
int p,c=1;
while (c==1)
{
printf("\nDoubly linked list");
printf("\n1: Create node");
printf("\n2: Insert node");
printf("\n3: Delete node");
printf("\n4: Display node");
printf("\n5: Exit program");
printf("\nEnter choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
del();
break;
case 4:
display();
break;
case 5:
c=2;
break;
default:
printf("\nBad input");
}
}
return 0;
}
e) Assess the suitability of a singly linked list for representing train routes between
stations. Implement operations for adding a new station and deleting an existing
station. Compare its performance with an array-based implementation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char station[50];
int distance;
struct node* link;
};
struct node *first=NULL,*cur=NULL,*temp=NULL;
void add()
{
cur=(struct node*)malloc(sizeof(struct node));
printf("\nEnter station name: ");
scanf("%s",cur->station);
printf("Enter distance to the next station: ");
scanf("%d",&cur->distance);
cur->link=NULL;
if(first==NULL)
{
first=cur;
printf("\nRoute starting station added.");
}
else
{
temp=first;
while(temp->link!=NULL)
{
temp=temp->link;
}
temp->link=cur;
printf("\nStation added to the route.");
}
}
void del()
{
char sname[50];
int found=0;
if(first==NULL)
{
printf("\nThe route is empty, no station to delete.");
return;
}
printf("\nEnter station name to delete: ");
scanf("%s",sname);
temp=first;
struct node* prev=NULL;
while(temp!=NULL)
{
if(strcmp(temp->station,sname)==0)
{
found=1;
if(prev==NULL)
{
first=temp->link;
}
else
{
prev->link=temp->link;
}
printf("\nStation '%s' deleted.",sname);
break;
}
prev=temp;
temp=temp->link;
}
if(found==0)
{
printf("\nStation '%s' not found in the route.",sname);
}
}
void display()
{
if(first==NULL)
{
printf("\nThe route is empty.");
}
else
{
temp=first;
printf("\nTrain Route:\n");
while(temp!=NULL)
{
printf("%s (%d km)",temp->station,temp->distance);
temp=temp->link;
if(temp!=NULL)
{
printf(" -> ");
}
}
printf("\n");
}
}
int main()
{
int c=1,p;
printf("\nTrain Route System");
while(c==1)
{
printf("\n1: Add station");
printf("\n2: Delete station");
printf("\n3: Display route");
printf("\n4: Exit");
printf("\nEnter choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
add();
break;
case 2:
del();
break;
case 3:
display();
break;
case 4:
c=0;
break;
default:
printf("\nBad input.");
}
}
return 0;
}
Performance comparison
4)
a) Construct a binary search tree from the elements {15, 10, 20, 8, 12, 17, 25} and
perform in-order, pre-order, and post-order traversals.
Elements={15,10,20,8,12,17,25}
Constructing binary tree-
Step 1-
Step 2-
Step 3-
Step 4-
Step 5-
Step 6-
in-order
LNR[Left-Node-Right]: {8,10,12,15,17,20,25}
pre-order
NLR[Node-Left-Right]: {15,10,8,12,20,17,25}
post-order
LRN[Left-Right-Node]: {8,12,10,17,25,20,15}
b) Differentiate between AVL trees and Binary Search Trees. Explain the
significance of balancing in AVL trees with an example
Binary Search Tree AVL Tree
• It is not a balanced tree. • It is a balanced tree.
• Nodes do not have to follow • Nodes haves to follow balance
balance factor. factor (i.e. difference between
depth of left and right subtree
should be either 0,1 or -1).
• The depth of tree is O(n). • The depth of tree is O(logn).
• Insertions and deletions are easy • Insertions and deletions require
because no rotations are required. rotations.
• Inefficient searching since there • Searching is efficient and faster
are large number of nodes due to balancing of depth.
• Simple to implement • Complex to implement
Note:- Every AVL tree is a binary search tree but not every binary search tree is an AVL
tree.
Significance
As mentioned before, AVL trees differ from binary search trees because of their balance
factor at every node and this is a key reason to which they are used. The balance factor
ensures that the that tree is a balanced tree and this ensures faster searching as we will
see in the example below.
Consider this example for the binary search tree, Now to access element 1, we will have
to go through 4 levels. Now let’s see the same example through an AVL three which is a
balanced binary search tree.
In this, we only have to go through two levels to access the element 1. This shows the
efficiency in traversing elements through the AVL tree when compared to a binary
search tree.
c) Explain and implement the insertion and rotation process in AVL trees to
maintain balance. Provide a step-by-step example for inserting {10, 20, 30, 15, 25}.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
int height;
};
struct node *root=NULL,*left=NULL,*right=NULL,*temp=NULL;
int height(struct node *n)
{
if(n==NULL)
{
return 0;
}
else
{
return n->height;
}
}
int getbal(struct node *n)
{
if(n==NULL)
{
return 0;
}
else
{
return height(n->left)-height(n->right);
}
}
struct node *rr(struct node *y)
{
struct node *x=y->left;
struct node *T2=x->right;
x->right=y;
y->left=T2;
if(height(y->left)>height(y->right))
{
y->height=height(y->left)+1;
}
else
{
y->height=height(y->right)+1;
}
if(height(x->left)>height(x->right))
{
x->height=height(x->left)+1;
}
else
{
x->height=height(x->right)+1;
}
return x;
}
struct node *lr(struct node *x)
{
struct node *y=x->right;
struct node *T2=y->left;
y->left=x;
x->right=T2;
if(height(x->left)>height(x->right))
{
x->height=height(x->left)+1;
}
else
{
x->height=height(x->right)+1;
}
if(height(y->left)>height(y->right))
{
y->height=height(y->left)+1;
}
else
{
y->height=height(y->right)+1;
}
return y;
}
struct node *insert(struct node *node,int data)
{
if(node==NULL)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data=data;
temp->left=NULL;
temp->right=NULL;
temp->height=1;
return temp;
}
if(data<node->data)
{
node->left=insert(node->left,data);
}
else if(data>node->data)
{
node->right=insert(node->right,data);
}
else
{
return node;
}
if(height(node->left)>height(node->right))
{
node->height=height(node->left)+1;
}
else
{
node->height=height(node->right)+1;
}
int bal=getbal(node);
if(bal>1&&data<node->left->data)
{
return rr(node);
}
if(bal<-1&&data>node->right->data)
{
return lr(node);
}
if(bal>1&&data>node->left->data)
{
node->left=lr(node->left);
return rr(node);
}
if(bal<-1&&data<node->right->data)
{
node->right=rr(node->right);
return lr(node);
}
return node;
}
void createnode()
{
int data;
printf("\nEnter data: ");
scanf("%d",&data);
root=insert(root,data);
}
void insertnode()
{
int data;
if(root==NULL)
{
printf("\nTree is empty. Create root first.");
return;
}
printf("\nEnter data: ");
scanf("%d",&data);
root=insert(root,data);
}
void display(struct node *node,int level)
{
if(node!=NULL)
{
display(node->right,level+1);
int i;
for(i=0;i<level;i++)
{
printf(" ");
}
printf("%d\n",node->data);
display(node->left,level+1);
}
}
int main()
{
int p,c=1;
while(c==1)
{
printf("\nAVL Tree");
printf("\n1: Create root");
printf("\n2: Insert node");
printf("\n3: Display nodes");
printf("\n4: Exit program");
printf("\nEnter choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
if(root==NULL)
{
printf("\nTree is empty.");
}
else
{
printf("\nTree structure:\n");
display(root,0);
}
break;
case 4:
c=2;
break;
default:
printf("\nBad input");
}
}
}
AVL tree for {10,20,30,15,25}
Step 1
Step 2
Balance Factor= 2
Balance Factor= 1
Balance Factor= 0
Single rotation is performed on the tree since imbalance(balance factor is not -1,0 or 1)
is seen at level 1.
Step 3
There is no imbalance at any node.
d) Construct an AVL tree for a financial application that tracks stock prices.
Demonstrate how balance is maintained during insertion and deletion operations,
and critique its applicability to high-frequency trading systems.
#include <stdio.h>
#include <stdlib.h>
struct node
{
float price;
struct node *left;
struct node *right;
int height;
};
struct node *root=NULL,*temp=NULL;
int height(struct node *n)
{
if(n==NULL)
{
return 0;
}
else
{
return n->height;
}
}
int getbal(struct node *n)
{
if(n==NULL)
{
return 0;
}
else
{
return height(n->left)-height(n->right);
}
}
struct node *rr(struct node *y)
{
struct node *x=y->left;
struct node *T2=x->right;
x->right=y;
y->left=T2;
if(height(y->left)>height(y->right))
{
y->height=height(y->left)+1;
}
else
{
y->height=height(y->right)+1;
}
if(height(x->left)>height(x->right))
{
x->height=height(x->left)+1;
}
else
{
x->height=height(x->right)+1;
}
return x;
}
root->height=1+((height(root->left)>height(root->right))?height(root-
>left):height(root->right));
int bal=getbal(root);
if(bal>1&&getbal(root->left)>=0)
{
return rr(root);
}
if(bal<-1&&getbal(root->right)<=0)
{
return lr(root);
}
if(bal>1&&getbal(root->left)<0)
{
root->left=lr(root->left);
return rr(root);
}
if(bal<-1&&getbal(root->right)>0)
{
root->right=rr(root->right);
return lr(root);
}
return root;
}
void createnode()
{
float price;
printf("\nEnter stock price: ");
scanf("%f",&price);
root=insert(root,price);
}
void insertnode()
{
float price;
if(root==NULL)
{
printf("\nTree is empty. Create root first.");
return;
}
printf("\nEnter stock price: ");
scanf("%f",&price);
root=insert(root,price);
}
void delf()
{
float price;
if(root==NULL)
{
printf("\nTree is empty.");
return;
}
printf("\nEnter stock price to delete: ");
scanf("%f",&price);
root=del(root, price);
}
void display(struct node *node,int level)
{
if(node!=NULL)
{
display(node->right,level+1);
int i;
for(i=0;i<level;i++)
{
printf(" ");
}
printf("%f\n",node->price);
display(node->left,level+1);
}
}
int main()
{
int p,c=1;
while(c==1)
{
printf("\nAVL Tree for Stock Prices");
printf("\n1: Create root");
printf("\n2: Insert stock price");
printf("\n3: Delete stock price");
printf("\n4: Display stock prices");
printf("\n5: Exit program");
printf("\nEnter choice: ");
scanf("%d",&p);
switch(p)
{
case 1:
createnode();
break;
case 2:
insertnode();
break;
case 3:
delf();
break;
case 4:
if(root==NULL)
{
printf("\nTree is empty.");
}
else
{
printf("\nStock prices tree structure:\n");
display(root,0);
}
break;
case 5:
c=2;
break;
default:
printf("\nBad input");
}
}
}
During the insertion and deletion operations, there are four possible imbalances:-
1. LL imbalance: Left subtree of the left child is taller, Right rotation is performed on
unbalanced node.
2. RR imbalance: Right subtree of the right child is taller, Left rotation is performed
on unbalanced node.
3. LR imbalance: Right subtree of the left child is taller, Left rotation is performed
on left child, followed by right rotation on unbalanced node.
4. RL imbalance: Left subtree of the right child is taller, Right rotation is performed
on the right child, followed by left rotation on unbalanced node.
1. Overhead of balancing –
During balancing at times multiple rotations are performed and this results in
computational overhead (i.e. overuse of resources, CPU time, memory,
processing power, etc.). And during times when low latency is required, overhead
of AVL trees would be a hindrance when there are thousands of updates per
second.
2. Time complexity-
HFT systems often deal with real-streaming data where data flows in at superfast
speeds and balancing operations wont be able to keep up pace with them.
3. Memory considerations-
AVL trees require more memory than simpler data structures like hash tables
and hence alternatives are considered.
5.
a) Demonstrate the working of the quick sort algorithm on the array {45, 23, 53,
21, 17}.
Quicksort algorithm-
WHILE too_small_index>too_big_index
WHILE data[too_big_index]<=data[pivot]
++too_big_index
WHILE data[too_small_index]>data[pivot]
--too_small_index
IF too_big_index<too_small_index
tbi tsi
45 is set as the pivot element
45 23 53 21 17 23 is set as toobig element
17 is set as toosmall element
0 1 2 3 4
tbi tsi
Since toobig element was smaller
45 23 53 21 17 than pivot 45, tbi index is
incremented.
0 1 2 3 4
tbi tsi
Since, toosmall element was not
45 23 17 21 53 bigger than pivot 45, no change in
element, and since tbi<tsi, data is
swappped
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
tsi tbi
Since toosmall element is bigger
than pivot (45), it is decremented to
45 23 17 21 53
3, now pointing to 21.
0 1 2 3 4
Now, finally, tsi is smaller than tbi so,
it exits the loop and pivot is swapped
21 23 17 45 53 with tsi value, leaving two sub-arrays
left and right of 45.
0 1 2 3 4
tbi tsi
Now, 23 is the new toobig element
21 23 17 45 53 and 17 becomes new toosmall
element.
0 1 2 3 4
tbi tsi
Both conditions, toobig(23)<pivot(21)
and toosmall(17)>pivot(21) are
21 17 23 45 53
unsatisfied and tbi<tsi is true after
which, values are swapped.
0 1 2 3 4
0 1 2 3 4
tbi, tsi The toosmall(23)>pivot(21) is true
after which tsi index is decremented.
21 17 23 45 53
0 1 2 3 4
#include <stdlib.h>
int empty=-2;
int htab[10];
return key%10;
int i=hash(key);
i=(i+1)%10;
htab[i]=key;
int i=hash(key);
int t=i;
while(htab[i]!=empty)
IF (htab[i]==key)
return i;
else
i=(i+1)%10;
IF(i==t)
break;
return -1;
int i=search(key);
IF (i==-1)
else
{
int t=htab[i];
htab[i]=empty;
void display()
printf("\nHash table");
for(int i=0;i<10;i++)
IF(htab[i]==empty)
printf("\n%d: empty");
else
printf("\n%d: %d",i,htab[i]);
int main()
htab[i]=empty;
int c=1,p,k;
while (c==1)
{
printf("\nHash table");
printf("\n1: Insert");
printf("\n2: Delete");
printf("\n3: Display");
printf("\n4: Search");
scanf("%d",&p);
switch(p)
case 1:
scanf("%d",&k);
insert(k);
break;
case 2:
scanf("%d",&k);
del(k);
break;
case 3:
display();
break;
case 4:
scanf("%d",&k);
search(k);
break;
case 5:
c=2;
break;
default:
printf("\nBad input");
As seen in the program, there is a collision resolution and for this program especially, it
uses linear probing which includes incrementing value by 1 until an empty slot is found.
i=(i+1)%10; in the insert()
Once it reaches the end say i=10, then new value of I becomes 1 which was the initial
value. This is why linear probing is used, it helps in returning the index to the beginning.
c) Implement a search engine feature where user queries are stored in a hash table.
Include collision resolution using chaining. Demonstrate how queries are added,
searched, and deleted.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
char query[100];
struct node*link;
};
struct node*htab[10],*temp=NULL,*prev=NULL;
int hash(char*query)
int sum=0;
for(int i=0;query[i]!='\0';i++)
sum+=query[i];
return sum%10;
}
void insert(char*query)
int i=hash(query);
strcpy(temp->query,query);
temp->link=NULL;
if(htab[i]==NULL)
htab[i]=temp;
else
temp->link=htab[i];
htab[i]=temp;
void search(char*query)
int i=hash(query);
temp=htab[i];
while(temp!=NULL)
if(strcmp(temp->query,query)==0)
return;
temp=temp->link;
return;
}
void del(char*query)
int i=hash(query);
temp=htab[i];
prev=NULL;
while(temp!=NULL)
if(strcmp(temp->query,query)==0)
if(prev==NULL)
htab[i]=temp->link;
else
prev->link=temp->link;
printf("\nQuery deleted");
return;
prev=temp;
temp=temp->link;
void display()
for(int i=0;i<10;i++)
{
temp=htab[i];
printf("\n%d: ",i);
while(temp!=NULL)
printf("%s ",temp->query);
temp=temp->link;
int main()
for(int i=0;i<10;i++)
htab[i]=NULL;
int c=1,p;
char query[100];
while(c==1)
scanf("%d",&p);
switch(p)
case 1:
printf("\nEnter query: ");
scanf("%s",query);
insert(query);
break;
case 2:
scanf("%s",query);
del(query);
break;
case 3:
display();
break;
case 4:
scanf(" %s",query);
search(query);
break;
case 5:
c=2;
break;
default:
printf("\nBad input");
return 0;
query here is a character array and we cannot perform modulo division directly to get a hash value, so we have to
go for alternative options. Here, a for loop can be used to add all the character to integer values and store it into a
variable sum on which the modulo division can be performed.
int hash(char*query)
int sum=0;
for(int i=0;query[i]!='\0';i++)
{
sum+=query[i];
return sum%10;
Chaining is handled here by chaining which includes usage of singley linked lists.
For deletion of queries, the function has a temp pointer that points to htab[i] where i is the hash key of the
entered query. Another linked list prev is used to store the previous elements linked to the node with target query.
The search function uses the hash key of the entered query and then traverses through the temp linked list using
temp=temp → link as long as the temp is not NULL.
Code-
#include <stdio.h>
int n2=high-mid;
L[i]=a[low+i];
R[j]=a[mid+j+1];
printf("%d ",L[i]);
printf("%d ",R[j]);
printf("\n");
int i=0,j=0,k=low;
IF (L[i]<=R[j])
a[k]=L[i];
i++;
else
{
a[k]=R[j];
j++;
k++;
while (i<n1)
a[k]=L[i];
i++;
k++;
while (j<n2)
a[k]=R[j];
j++;
k++;
printf("%d ",a[i]);
IF (low<high)
int mid=low+(high-low)/2;
mergesort(a,low,mid);
mergesort(a,mid+1,high);
merge(a,low,mid,high);
int main()
int n;
scanf("%d",&n);
int a[n];
printf("\n");
scanf("%d",&a[i]);
mergesort(a,0,n-1);
printf("%d ",a[i]);
printf("\n");
return 0;
Output-
6)
a) Design and implement Depth First Search (DFS) and Breadth First Search
(BFS) algorithms for a graph represented as an adjacency matrix. Use an
example graph to demonstrate both traversals.
BFS algorithm pseudocode
int visited[50]
int q[50]
bfs(graph, n, start)
q[50] ->EMPTY
visited[i]=0
ENQUEUE start->q
visited[start]=1
PRINT vertex
ENQUEUE i to q
visited[i]=1
visited[vertex]=1
PRINT vertex
dfs(graph, visited, i, n)
0 1 2 3 4
0 0 1 1 0 0
1 1 0 0 1 1
2 1 0 0 0 0
3 0 1 0 0 0
4 0 1 0 0 0
BFS Output
Step ->Enqueue start vertex -> 0
1: q=[0]
visited=[1,0,0,0,0]
Step ->Dequeue vertex 0 0
2: q=[]
current vertex=0
q=[1] (1 is adjacent)
visited=[1,1,0,0,0]
q=[1,2] (2 is adjacent)
visited=[1,1,1,0,0]
Step ->Dequeue vertex 1 1
3: q=[2]
current vertex=1
q=[2,3] (3 is adjacent)
visited=[1,1,1,1,0]
q=[2,3,4]
visited=[1,1,1,1,1]
Step ->Dequeue vertex 2 2
4: q=[3,4]
current vertex=2
Step ->Dequeue vertex 3 3
5: q=[4]
current vertex=3
Step ->Dequeue vertex 4 4
6: q=[]
current vertex=4
Step ->Termination
7:
0->1->2->3->4
DFS Output
Step ->vertex 0 is visited 0
1: visited=[1,0,0,0,0]
0->1->3->4->2
b) Model a city's road network as a graph where intersections are nodes and roads
are edges. Use Dijkstra's algorithm to find the shortest path between two
intersections. Illustrate the process with an example.
4
4
1 2
3
2 1
4 2
1
6
Consider this graph with nodes A,B, C, D, E, F and G and respective roads with
distances. The shortest path is calculated using Dijkstra’s algorithm as shown below-
Vertex A B C D E F G
Status 0 1 1 1 1 1 1
Distance 0 3 6 - - - -
Next * A A A A A A
Vertex A B C D E F G
Status 0 0 1 1 1 1 1
Distance 0 3 5 7 - - -
Next * A B B A A A
Vertex A B C D E F G
Status 0 0 0 1 1 1 1
Distance 0 3 5 6 9 7 -
Next * A B C C C A
Vertex A B C D E F G
Status 0 0 0 0 1 1 1
Distance 0 3 5 6 8 7 10
Next * A B C D C D
Vertex A B C D E F G
Status 0 0 0 0 1 0 1
Distance 0 3 5 6 8 7 8
Next * A B C D C F
Vertex A B C D E F G
Status 0 0 0 0 0 0 1
Distance 0 3 5 6 8 7 8
Next * A B C D C F
Vertex A B C D E F G
Status 0 0 0 0 0 0 0
Distance 0 3 5 6 8 7 8
Next * A B C D C F
c) Design a social network graph where individuals are nodes and friendships
are edges. Implement BFS and DFS to find the shortest connection between two
individuals and all friends of a given person.
Consider the following graph with nodes as the individuals and edges as friendships-
BFS Output
Step ->Enqueue start vertex -> 0
1: q=[0]
visited=[1,0,0,0,0]
Step ->Dequeue vertex 0 0
2: q=[]
current vertex=0
q=[1] (1 is adjacent)
visited=[1,1,0,0,0]
q=[1,2] (2 is adjacent)
visited=[1,1,1,0,0]
q=[1,2,4] (4 is adjacent)
visited=[1,1,1,0,1]
Step ->Dequeue vertex 1 1
3: q=[2,4]
current vertex=1
q=[2,4,3] (3 is adjacent)
visited=[1,1,1,1,1]
Step ->Dequeue vertex 2 2
4: q=[3,4]
current vertex=2
Step ->Dequeue vertex 4 4
5: q=[3]
current vertex=4
Step ->Dequeue vertex 3 3
6: q=[]
current vertex=3
Step ->Termination
7:
0->1->2->4->3
DFS Output
Step ->vertex 0 is visited 0
1: visited=[1,0,0,0,0]
Adjacent vertices- 3
Step ->vertex 3 is visited 0->1->3
3: visited=[1,1,0,1,0]
Backtrack to 3
Adjacent vertices- 4
Step ->vertex 4 is visited 0->1->3->2->4
5: visited=[1,1,1,1,1]
0->1->3->2->4
Step 1
Step 2
Plot graph
Step 1
Vertex A B C D E F
Status 0 1 1 1 1 1
Cost - 5 7 - - -
Next * A A A A A
Step 2
Vertex A B C D E F
Status 0 0 1 1 1 1
Cost - 5 2 3 4 1
Next * A B B B B
Step 3
Vertex A B C D E F
Status 0 0 1 1 1 0
Cost - 5 2 2 4 1
Next * A B F B B
Step 4
Vertex A B C D E F
Status 0 0 0 1 1 0
Cost - 5 2 2 3 1
Next * A B F C B
Step 5
Vertex A B C D E F
Status 0 0 0 0 1 0
Cost - 5 2 2 3 1
Next * A B F C B
Step 6
Vertex A B C D E F
Status 0 0 0 0 1 0
Cost - 5 2 2 3 1
Next * A B F C B
Kruskal’s Prim’s
Edge list graph representation Adjacency matrix representation
Time complexity of O(ElogE) Time complexity of O(E+VlogV)
Sparse graphs Dense graphs
Harder to increment Easier to increment
Sorting all edges is required Sorting is not required
Less suitable for large graphs More suitable