Queues Doc1
Queues Doc1
After deleting an element, the value of front will increase from -1 to 0. however, the queue
will look something like following.
Algorithm to insert any element in a queue
Check if the queue is already full by comparing rear to max - 1. if so, then return an overflow
error.
If the item is to be inserted as the first element in the list, in that case set the value of
front and rear to 0 and insert the element at the rear end.
Otherwise keep increasing the value of rear and insert each element one by one
having rear as the index.
Algorithm
Write OVERFLOW
Go to step
[END OF IF]
ELSE
[END OF IF]
Step 3: Set QUEUE[REAR] = NUM
Step 4: EXIT
void insert (int queue[], int max, int front, int rear, int item)
{
if (rear + 1 == max)
{
printf("overflow");
}
else
{
if(front == -1 && rear == -1)
{
front = 0;
rear = 0;
}
else
{
rear = rear + 1;
}
queue[rear]=item;
}
}
Otherwise, keep increasing the value of front and return the item stored at the front
end of the queue at each time.
Algorithm
Step 1: IF FRONT = -1 or FRONT > REAR
Write UNDERFLOW
ELSE
[END OF IF]
Step 2: EXIT
int delete (int queue[], int max, int front, int rear)
{
int y;
if (front == -1 || front > rear)
{
printf("underflow");
}
else
{
y = queue[front];
if(front == rear)
{
front = rear = -1;
else
front = front + 1;
}
return y;
}
}
In a linked queue, each node of the queue consists of two parts i.e. data part and the link part.
Each element of the queue points to its immediate next element in the memory.
In the linked queue, there are two pointers maintained in the memory i.e. front pointer and
rear pointer. The front pointer contains the address of the starting element of the queue while
the rear pointer contains the address of the last element of the queue.
Insertion and deletions are performed at rear and front end respectively. If front and
rear both are NULL, it indicates that the queue is empty.
Insert operation
The insert operation append the queue by adding an element to the end of the
queue. The new element will be the last element of the queue.
Firstly, allocate the memory for the new node ptr by using the following statement.
There can be the two scenario of inserting this new node ptr into the linked queue.
In thhe first scenario, we insert element into an empty queue. In this case, the
condition front = NULL becomes true. Now, the new element will be added as the
only element of the queue and the next pointer of front and rear pointer both, will
point to NULL.
In the second case, the queue contains more than one element. The condition front
= NULL becomes false. In this scenario, we need to update the end pointer rear so
that the next pointer of rear will point to the new node ptr. Since, this is a linked
queue, hence we also need to make the rear pointer point to the newly added
node ptr. We also need to make the next pointer of rear point to NULL.
In this way, the element is inserted into the queue. The algorithm and the C
implementation is given as follows.
Algorithm
ELSE
[END OF IF]
Step 4: END
Deletion
Deletion operation removes the element that is first inserted among all the queue
elements. Firstly, we need to check either the list is empty or not. The condition front
== NULL becomes true if the list is empty, in this case , we simply write underflow on
the console and make exit.
Otherwise, we will delete the element that is pointed by the pointer front. For this
purpose, copy the node pointed by the front pointer into the pointer ptr. Now, shift
the front pointer, point to its next node and free the node pointed by the node ptr.
This is done by using the following statements.
ptr = front;
front = front -> next;
free(ptr);
The algorithm and C function is given as follows.
Algorithm
Go to Step 5
[END OF IF]
Step 5: END
Circular Queue
Circular Queue
Why was the concept of the circular queue
introduced?
There was one limitation in the array implementation of Queue. If the rear reaches to the end
position of the Queue then there might be possibility that some vacant spaces are left in the
beginning which cannot be utilized. So, to overcome such limitations, the concept of the
circular queue was introduced.
As we can see in the above image, the rear is at the last position of the Queue and front is
pointing somewhere rather than the 0th position. In the above array, there are only two
elements and other three positions are empty. The rear is at the last position of the Queue; if
we try to insert the element then it will show that there are no empty spaces in the Queue.
There is one solution to avoid such wastage of memory space by shifting both the elements at
the left and adjust the front and rear end accordingly. It is not a practically good approach
because shifting all the elements will consume lots of time. The efficient approach to avoid
the wastage of the memory is to use the circular queue data structure.
Enqueue operation
The steps of enqueue operation are given below:
o If rear != max - 1, then rear will be incremented to mod(maxsize) and the new
value will be inserted at the rear end of the queue.
o If front != 0 and rear = max - 1, it means that queue is not full, then set the value of
rear to 0 and insert the new element there.
o When front ==0 && rear = max-1, which means that front is at the first position of
the Queue and rear is at the last position of the Queue.
o front== rear + 1;
Goto step 4
[End OF IF]
SET REAR = 0
ELSE
[END OF IF]
Step 4: EXIT
Dequeue Operation
The steps of dequeue operation are given below:
o First, we check whether the Queue is empty or not. If the queue is empty, we cannot
perform the dequeue operation.
o When the element is deleted, the value of front gets decremented by 1.
o If there is only one element left which is to be deleted, then the front and rear are
reset to -1.
Step 1: IF FRONT = -1
Goto Step 4
[END of IF]
ELSE
IF FRONT = MAX -1
SET FRONT = 0
ELSE
[END of IF]
[END OF IF]
Step 4: EXIT
Let's understand the enqueue and dequeue operation through the diagrammatic representation.
Program
#include <stdio.h>
# define max 6
int queue[max]; // array declaration
int front=-1;
int rear=-1;
// function to insert an element in a circular queue
void enqueue(int element)
{
if(front==-1 && rear==-1) // condition to check queue is empty
{
front=0;
rear=0;
queue[rear]=element;
}
else if((rear+1)%max==front) // condition to check queue is full
{
printf("Queue is overflow..");
}
else
{
rear=(rear+1)%max; // rear is incremented
queue[rear]=element; // assigning a value to the queue at the rear position.
}
}
switch(choice)
{
case 1:
}}
return 0;
}
Double-ended queue
Though the insertion and deletion in a deque can be performed on both ends, it
does not follow the FIFO rule. The representation of a deque is given as follows -
Types of deque
There are two types of deque -
In input restricted queue, insertion operation can be performed at only one end,
while deletion can be performed from both ends.
In output restricted queue, deletion operation can be performed at only one end,
while insertion can be performed from both ends.
Operations performed on deque
There are the following operations that can be applied on a deque -
o Insertion at front
o Insertion at rear
o Deletion at front
o Deletion at rear
We can also perform peek operations in the deque along with the operations listed
above. Through peek operation, we can get the deque's front and rear elements of
the deque. So, in addition to the above operations, following operations are also
supported in deque -
In this operation, the element is inserted from the front end of the queue. Before
implementing the operation, we first have to check whether the queue is full or not.
If the queue is not full, then the element can be inserted from the front end by using
the below conditions -
o If the queue is empty, both rear and front are initialized with 0. Now, both will point
to the first element.
o Otherwise, check the position of the front if the front is less than 1 (front < 1), then
reinitialize it by front = n - 1, i.e., the last index of the array.
Insertion at the rear end
In this operation, the element is inserted from the rear end of the queue. Before
implementing the operation, we first have to check again whether the queue is full or
not. If the queue is not full, then the element can be inserted from the rear end by
using the below conditions -
o If the queue is empty, both rear and front are initialized with 0. Now, both will point
to the first element.
o Otherwise, increment the rear by 1. If the rear is at last index (or size - 1), then instead
of increasing it by 1, we have to make it equal to 0.
If the queue is empty, i.e., front = -1, it is the underflow condition, and we cannot
perform the deletion. If the queue is not full, then the element can be inserted from
the front end by using the below conditions -
If the deque has only one element, set rear = -1 and front = -1.
Else if front is at end (that means front = size - 1), set front = 0.
In this operation, the element is deleted from the rear end of the queue. Before
implementing the operation, we first have to check whether the queue is empty or
not.
If the queue is empty, i.e., front = -1, it is the underflow condition, and we cannot
perform the deletion.
If the deque has only one element, set rear = -1 and front = -1.
This operation is performed to check whether the deque is empty or not. If front = -
1, it means that the deque is empty.
Check full
This operation is performed to check whether the deque is full or not. If front = rear
+ 1, or front = 0 and rear = n - 1 it means that the deque is full.
The time complexity of all of the above operations of the deque is O(1), i.e., constant.
Applications of deque
o Deque can be used as both stack and queue, as it supports both operations.
o Deque can be used as a palindrome checker means that if we read the string from
both ends, the string would be the same.
Program
#include <stdio.h>
#define size 5
int deque[size];
int f = -1, r = -1;
// insert_front function will insert the value from the front
void insert_front(int x)
{
if((f==0 && r==size-1) || (f==r+1))
{
printf("Overflow");
}
else if((f==-1) && (r==-1))
{
f=r=0;
deque[f]=x;
}
else if(f==0)
{
f=size-1;
deque[f]=x;
}
else
{
f=f-1;
deque[f]=x;
}
}
while(i!=r)
{
printf("%d ",deque[i]);
i=(i+1)%size;
}
printf("%d",deque[r]);
}
}
else if(f==(size-1))
{
printf("\nThe deleted element is %d", deque[f]);
f=0;
}
else
{
printf("\nThe deleted element is %d", deque[f]);
f=f+1;
}
}
}
else if(r==0)
{
printf("\nThe deleted element is %d", deque[r]);
r=size-1;
}
else
{
printf("\nThe deleted element is %d", deque[r]);
r=r-1;
}
}
int main()
{
insert_front(20);
insert_front(10);
insert_rear(30);
insert_rear(50);
insert_rear(80);
display(); // Calling the display function to retrieve the values of deque
getfront(); // Retrieve the value at front-end
getrear(); // Retrieve the value at rear-end
delete_front();
delete_rear();
display(); // calling display function to retrieve values after deletion
return 0;
}
insert_front(14);
insert_rear(34);
insert_rear(64);
insert_rear(74); delete_front();
delete_rear();