DSA m2
DSA m2
A Queue is a data structure in which we can add element only at one end, called the rear of the queue, and delete
element only at the other end, called the front of the queue.
To understand how the above operations work on a queue. See the example given below.
From the above image, we can see that when we add a new element in the queue, the variable R is increased by
1, and the new element is added at the new position of R. Similarly, when we delete an element from the queue,
the variable F is increased by 1.
The queue behaves like a first in first out manner. It means that the elements that are added first to the queue,
are removed first from the queue.
So a queue is also known as FIFO (First In First Out) data structure.
In the above image, we can see an array named arr whose size is 5. We take two variables R and F, The
variable R stands for rear and the default value is -1. The variable F stands for front and the default value is 0.
For add operation in the queue first, we check if the value of R is equal to the value of size-1 then, we will
display a message Queue is full, else we will increase the value of R by 1 and add the element in the array at the
new location of R.
Example
if(R==size-1)
{
printf("Queue is full\n");
}
else
{
R=R+1;
arr[R]=new_item;
}
If we add three elements, say 12, 15 and 26 in the queue, then the queue will look like as shown in the image
below.
For delete operation in the queue first, we check if the value of F is greater than the value of R then, we will
display a message Queue is empty, else we will display the deleted element on the screen and then increase
the value of F by 1.
Example
if(F>R)
{
printf("Queue is empty\n");
}
else
{
printf("Element Deleted = %d",arr[F]);
F=F+1;
}
If we delete the first elements 12 from the queue, then the queue will look like as shown in the image below.
#include <stdio.h>
#include <stdlib.h>
#define size 5
int main()
{
int arr[size],R=-1,F=0,ch,n,i;
switch(ch)
{
case 1:
if(R==size-1)
printf("Queue is full");
else
{
printf("Enter a number ");
scanf("%d",&n);
R++;
arr[R]=n;
}
break;
case 2:
if(F>R)
printf("Queue is empty");
else
{
printf("Number Deleted = %d",arr[F]);
F++;
}
break;
case 3:
if(F>R)
printf("Queue is empty");
else
{
for(i=F; i<=R; i++)
printf("%d ",arr[i]);
}
break;
case 4: exit(0);
A Circular Queue is used to overcome the limitation we face in the array implementation of a Queue. The
problem is that when the rear reaches the end and if we delete some elements from the front and then try to
add a new element in the queue, it says "Queue is full", but still there are spaces available in the queue. See the
example given below.
In the above image, the queue is full because the rear R reached the end of the queue. We have deleted two
elements from the queue, so the front F is at index 2. We can see that there are spaces available in the queue,
but we can't add a new element because the rear can't go back to index 0.
For add operation in the circular queue first, we check if the value of te is equal to the value of size then, we will
display a message Queue is full, else we will increase the value of R by R=(R+1)%Size and add the element in the
array at the new location of R and then increased the value of te by 1.
if(te==size)
{
printf("Queue is full\n");
}
else
{
R=(R+1)%size;
arr[R]=new_item;
te=te+1;
}
For delete operation in the circular queue first, we check if the value of te is 0 then, we will display a
message Queue is empty, else we will display the deleted element on the screen and then increase the value
of F by F=(F+1)%Size and then decrease the value of te by 1.
if(te==0)
{
printf("Queue is empty\n");
}
else
{
printf("Element Deleted = %d",arr[F]);
F=(F+1)%size;
te=te-1;
}
#include <stdio.h>
#include <stdlib.h>
#define size 5
int main()
{
int arr[size],R=-1,F=0,te=0,ch,n,i,x;
case 2:
if(te==0)
printf("Queue is empty");
else
{
printf("Number Deleted = %d",arr[F]);
F=(F+1)%size;
te=te-1;
}
break;
case 3:
if(te==0)
printf("Queue is empty");
else
{
x=F;
for(i=1; i<=te; i++)
{
printf("%d ",arr[x]);
x=(x+1)%size;
}
}
break;
case 4:
exit(0);
default:
printf("Wrong Choice");
}
}
return 0;
}
Singly Linked List
Singly Linked List is a linear and unidirectional data structure, where data is saved on the nodes, and each node
is connected via a link to its next node. Each node contains a data field and a link to the next node. Singly Linked
Lists can be traversed in only one direction.
struct Node {
int data;
struct Node* next;
};
Here’s the C code for inserting a node at the head of a linked list:
// Traverse the list to find the node with the specified searchItem
struct Node* current = head;
while (current != NULL && current->data != searchItem) {
current = current->next;
}
return head;
}
Delete the head node of the singly linked list
Step 1) Assign the next node of the head node as the new head.
Step 2) Free the allocated memory by the previous head node.
Step 3) Return the new head node.
return head;
}
After deleting the head
// If the list is empty or has only one element, free the head and return NULL
if (head == NULL || head->next == NULL) {
free(head);
return NULL;
}
// Free the last node and update the next pointer of the second-to-last node
free(current->next);
current->next = NULL;
return head;
}
Search and delete a node from a singly linked list
Step 1) Traverse until the end of the linked list. Check if the current node is equal to the search node or not.
Step 2) If any node matches, store the node pointer to the current node.
Step 3) The “next” of the previous node will be the next node of the current node.
Step 4) Delete and free the memory of the current node.
C code for search and delete a node from a singly linked list:
// Traverse the list to find the node with the specified searchItem
struct Node* current = head;
while (current->next != NULL && current->next->data != searchItem) {
current = current->next;
}
return head;
}
Traverse a singly linked list
Step 1) Traverse each node until we get null as the next node.
Step 2) Print the value of the current node.
Two conditions are checked while push or pop operation on the linked list.
1. Overflow: the stack is full; element cannot be inserted
2. Underflow: the stack is empty; cannot remove an element
Linked list representation of the stack allows it to grow or shrink without any prior fixed limit due to the
dynamic nature of the linked list. Diagram shows how a stack data structure can be represented using
linked list.
This is the linked list representation of a stack having four elements. The top most element is at the
beginning of the list. Here, the top most element is 80. And the oldest element is at the end of the list.
Here, the oldest element is 50. The first element of the linked list here is represented by a pointer variable
Top.
Push Operation
Push operation is the insertion of an element at the top of the stack. In case of linked list to represent
the stack, the push operation can be performed by inserting an element at the beginning of the linked
list. Here is the C code depicting the push operation on stack where, the element Data is inserted into
the stack using linked list. A stack pointer variable Top points to the top most element or node of the
stack.
Pop Operation
Pop operation is the deletion of an element from the stack that can be performed by deleting an element
at the beginning of the linked list. While performing pop operation, underflow condition must be checked.
Here, the underflow condition occurs when the stack is empty and we try to delete an element from the
stack. Here is an algorithm depicting the pop operation on stack, where, the first element or node pointed
by stack pointer variable Top is deleted.
if (top == NULL)
{
printf("Stack is Empty, Underflow Condition\n");
}
free(temp);
return data;
}
Linked Queues
Queue is a linear data structure which follows the property, First In first Out (FIFO) or First Come First
Serve (FCFS). The first inserted element will be the first to be removed. Queue has two ends, one is
Front and other is Rear. Front variable indicates the oldest element inserted into the queue and Rear
variable indicates the last element inserted into the queue.
Two conditions are checked while insertion or deletion operation on the linked list.
1. Overflow: the queue is full; element cannot be inserted
2. Underflow: the queue is empty; cannot remove an element
Linked list representation of the queue allows it to grow or shrink without any prior fixed limit due to the
dynamic nature of the linked list. Diagram shows how a queue data structure can be represented using
linked list.
Insertion Operation
The insertion of new element takes place at the rear end of the queue. Below is the diagram along with
algorithm for insertion of an element ‘e’ into the queue. The element ‘e’ is inserted at the Rear end of the
list.
// Define a structure for the node
struct Node
{
int info; // Data of the node
struct Node* next; // Pointer to the next node
};
newNode->info = data;
newNode->next = NULL;
if (rear == NULL)
{
front = rear = newNode;
}
else
{
rear->next = newNode;
rear = newNode;
}
Deletion operation
Deletion of an element from the will be performed at the beginning of the linked list. While deleting an
element from the queue, underflow condition must be checked. Here, the underflow condition occurs
when the queue is empty and we try to delete an element from the queue. Here is the algorithm depicting
the deletion operation on queue. The element at the front end of the queue is deleted.
// Function to remove an element from the queue
int dequeue()
{
if (front == NULL)
{
printf("Queue is Empty\n");
}
if (front == rear)
{
front = rear = NULL;
}
else
{
front = front->next;
}
free(temp);
return data;
}