Unit 2 Queue
Unit 2 Queue
3. For example, people waiting in line for a rail ticket form a queue.
Applications of Queue
Due to the fact that queue performs actions on first in first out basis which
is quite fair for the ordering of actions. There are various applications of
queues discussed as below.
1. Queues are widely used as waiting lists for a single shared resource like
printer, disk, CPU.
2. Queues are used in asynchronous transfer of data (where data is not being
transferred at the same rate between two processes) for eg. pipes, file IO,
sockets.
3. Queues are used as buffers in most of the applications like MP3 media
player, CD player, etc.
4. Queue are used to maintain the play list in media players in order to add
and remove the songs from the play-list.
5. Queues are used in operating systems for handling interrupts.
Types of Queue
In this article, we will discuss the types of queue. But before moving
towards the types, we should first discuss the brief introduction of the
queue.
What is a Queue?
Queue is the data structure that is similar to the queue in the real world. A
queue is a data structure in which whatever comes first will go out first,
and it follows the FIFO (First-In-First-Out) policy. Queue can also be
defined as the list or collection in which the insertion is done from one end
known as the rear end or the tail of the queue, whereas the deletion is
done from another end known as the front end or the head of the queue.
Types of Queue
There are four different types of queue that are listed as follows -
o Simple Queue or Linear Queue
o Circular Queue
o Priority Queue
o Double Ended Queue (or Deque)
The major drawback of using a linear Queue is that insertion is done only
from the rear end. If the first three elements are deleted from the Queue,
we cannot insert more elements even though the space is available in a
Linear Queue. In this case, the linear Queue shows the overflow condition
as the rear is pointing to the last element of the Queue.
To know more about the queue in data structure, you can click the link
- https://www.javatpoint.com/data-structure-queue
Circular Queue
In Circular Queue, all the nodes are represented as circular. It is similar to
the linear Queue except that the last element of the queue is connected
to the first element. It is also known as Ring Buffer, as all the ends are
connected to another end. The representation of circular queue is shown
in the below image -
To know more about the circular queue, you can click the link
- https://www.javatpoint.com/circular-queue
Priority Queue
It is a special type of queue in which the elements are arranged based on
the priority. It is a special type of queue data structure in which every
element has a priority associated with it. Suppose some elements occur
with the same priority, they will be arranged according to the FIFO
principle. The representation of priority queue is shown in the below
image -
Insertion in priority queue takes place based on the arrival, while deletion
in the priority queue occurs based on the priority. Priority queue is mainly
used to implement the CPU scheduling algorithms.
There are two types of priority queue that are discussed as follows -
To learn more about the priority queue, you can click the link
- https://www.javatpoint.com/ds-priority-queue
Deque can be used both as stack and queue as it allows the insertion and
deletion operations on both ends. Deque can be considered as stack
because stack follows the LIFO (Last In First Out) principle in which
insertion and deletion both can be performed only from one end. And in
deque, it is possible to perform both insertion and deletion from one end,
and Deque does not follow the FIFO principle.
o Enqueue: The Enqueue operation is used to insert the element at the rear
end of the queue. It returns void.
o Dequeue: It performs the deletion from the front-end of the queue. It also
returns the element which has been removed from the front-end. It
returns an integer value.
o Peek: This is the third operation that returns the element, which is
pointed by the front pointer in the queue but does not delete it.
o Queue overflow (isfull): It shows the overflow condition when the queue
is completely full.
o Queue underflow (isempty): It shows the underflow condition when the
Queue is empty, i.e., no elements are in the Queue.
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
Otherwise, keep increasing the value of front and return the item stored
at the front end of the queue at each time.
Algorithm
The above figure shows how the memory space is wasted in the array
representation of queue. In the above figure, a queue of size 10 having 3
elements, is shown. The value of the front variable is 5, therefore, we can
not reinsert the values in the place of already deleted element before the
position of front. That much space of the array is wasted and can not be
used in the future (for this queue).
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 the 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
o Step 1: Allocate the space for the new node PTR
o Step 2: SET PTR -> DATA = VAL
o Step 3: IF FRONT = NULL
SET FRONT = REAR = PTR
SET FRONT -> NEXT = REAR -> NEXT = NULL
ELSE
SET REAR -> NEXT = PTR
SET REAR = PTR
SET REAR -> NEXT = NULL
[END OF IF]
o 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.
1. ptr = front;
2. front = front -> next;
3. free(ptr);
The algorithm and C function is given as follows.
Algorithm
o Step 1: IF FRONT = NULL
Write " Underflow "
Go to Step 5
[END OF IF]
o Step 2: SET PTR = FRONT
o Step 3: SET FRONT = FRONT -> NEXT
o Step 4: FREE PTR
o Step 5: END
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 0 th 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 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;
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.
Algorithm to delete an element from the circular queue
Step 1: IF FRONT = -1
Write " UNDERFLOW "
Goto Step 4
[END of IF]
Step 4: EXIT
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.
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.
In this operation, the element is deleted from the front 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 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.
Check empty
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.