Queue
Queue
by
Farhan Sufyan
Contents
1 Queue 1
1.1 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Basic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3 Applications of Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4 Implementation of Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5 Implementation of Queue using Array - Static Implementation . . . . . . . . . . . . . . . . . . . 3
1.5.1 Implementation of Queue using Array (shifting elements after dequeue operation) . . . . . 3
1.5.1.1 Enqueue operation in a Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5.1.2 Dequeue operation in a Queue . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5.2 Implementation of Queue using Array (without shifting elements after dequeue operation) 5
1.5.2.1 Enqueue operation in a Queue (without shifting elements) . . . . . . . . . . . . 6
1.5.2.2 Dequeue operation in a Queue (without shifting elements) . . . . . . . . . . . . 6
1.6 Implementation of Queue using Linked List - Dynamic Implementation . . . . . . . . . . . . . . 7
1.6.1 Enqueue operation in a Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6.2 Dequeue operation in a Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.7 Implement Queue using Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7.1 Making an enqueue operation costly. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7.2 Making an dequeue operation costly. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.7.3 Home Assignment - Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7.4 Video Lectures for Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.8 Circular Queue (CQ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.8.1 Why Was the Concept of Circular Queue Introduced? . . . . . . . . . . . . . . . . . . . . 14
1.8.2 Applications of Circular Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.8.3 How to Implement a Circular Queue? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.8.4 Implement Circular Queue using Array - How you can achieve circular incrementation . . 15
1.8.5 Enqueue in Circular Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.8.6 Dequeue in Circular Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.8.7 Video Lectures for Circular Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.9 Double-Ended Queue (DQ) or Deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.9.1 Types of DQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.9.2 Applications of Deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.9.3 Deque Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.9.4 Operations on Deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.9.5 Home Assignment - Deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.9.6 Video Lecture on Deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.10 Self-Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.11 Priority Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.11.1 Application of Priority Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.11.2 Types of Priority Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.11.3 Implementation of Priority Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.11.3.1 Array Implementation of Priority Queue . . . . . . . . . . . . . . . . . . . . . 26
1.11.3.2 Linked List Implementation of Priority Queue . . . . . . . . . . . . . . . . . . 27
1.12 Sample Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Chapter 1
Queue
1.1 Queue
• Queue is a non-primitive linear DS.
• A queue is open at both its ends where element is inserted from one end called the REAR (also called tail)
and delete operation to be performed from the other end called FRONT (also called head).
• Queue is also referred to be as:
– FIFO (First In First Out)
– FCFS (First Come First Serve)
– LILO (Last In Last Out)
• For example, people waiting in line for a rail ticket form a queue.
1
1.3 Applications of Queue
• Queue DS can be used where a resource is shared among multiple consumers.
2
1.5 Implementation of Queue using Array - Static Implementation
1.5.1 Implementation of Queue using Array (shifting elements after dequeue operation)
3
1.5.1.1 Enqueue operation in a Queue
• Step 1 - Check whether queue is FULL (rear == SIZE-1).
• Step 2 - If it is FULL, then display "Queue is FULL!!! Insertion is not possible!!!" and terminate the function.
• Step 3 - Else (If it is NOT FULL), then increment rear value by one (rear = rear + 1) and set queue[rear] =
item.
void enqueue() {
if(isFull()) {
printf("Queue Overflow\n");
} else {
int item;
printf("Enter the element to be insert in queue: ");
scanf("%d",&item);
rear = rear + 1;
queue[rear] = item;
}
}
void dequeue() {
int data;
if(isEmpty()) {
printf("Cannot delete elements from the queue - Queue is Empty - Queue Underflow\n");
}
else {
data = queue[0];
printf("Dequeue element is : %d\n", data);
• Shifting the all the queue elements after the dequeue operation is costly and takes O(n) time.
• Hence, rather than shifting all the elements in queue to the front, we can take additional front pointer and
increment the front pointer after every dequeue operation (i.e. Implementation of Queue using Array -
without shifting the elements after dequeue operation).
4
1.5.2 Implementation of Queue using Array (without shifting elements after dequeue
operation)
Figure 1.3: Queue using Array (without shifting elements after dequeue operation)
5
1.5.2.1 Enqueue operation in a Queue (without shifting elements)
• Step 1 - Check whether queue is FULL (rear == SIZE-1).
• Step 2 - If it is FULL, then display "Queue is FULL!!! Insertion is not possible!!!" and terminate the function.
• Step 3 - Else (If it is NOT FULL), then set front = 0 and increment rear value by one (rear = rear + 1) and
set queue[rear] = item.
void enqueue() {
If(rear == size - 1) {
printf("Queue Overflow\n");
}
else {
If (front == -1) {
front = 0;
int item;
printf("Inset the element in queue : ");
scanf("%d", &item);
rear = rear + 1;
queue[rear] = item;
}
}
}
void dequeue() {
if(isEmpty()) {
printf("Cannot delete elements from the queue - Queue is Empty - Queue Underflow\n");
}
else {
int data;
data = queue[0];
front = front + 1;
printf("Dequeue element is : %d\n", data);
• If the queue has a large number of enqueue and dequeue operations, at some point we may not we able to
insert elements in the queue even if the queue is empty.
• Example is shown in Figure 1.4
• The efficient solution of this problem is using the concept of Circular Queue.
6
1.6 Implementation of Queue using Linked List - Dynamic Implementa-
tion
• In a linked queue, each node of the queue consists of two fields, i.e., data field and reference field.
• Each entity of the linked queue points to its immediate next entity in the memory.
• Furthermore, to keep track of the front and rear node, two pointers are preserved in the memory.
• The front pointer stores the address of the first element of the queue, and the rear pointer stores the address
of the last element of the queue.
• In case of Dynamic implementation or Linked List implementation of Queue, problem that are faced in array
implementation of queue are not encountered.
void enqueue(){
if(newNode == NULL){
printf("Unable to allocate memory.");
exit(0);
}
else{
printf("Enter the data: ");
scanf("%d", &item);
7
rear -> next = newNode;
rear = newNode;
}
printf("\nInsertion is Success!!!\n");
}
}
8
1.6.2 Dequeue operation in a Queue
• Step 1 - Check whether queue is Empty (front == NULL).
• Step 2 - If it is Empty, then display "Queue is Empty!!! Deletion is not possible!!!" and terminate from the
function
• Step 3 - If it is Not Empty then, define a Node pointer ’temp’ and set it to ’front’.
• Step 4 - Then set ’front = front next’ and delete ’temp’ (free(temp)).
void dequeue() {
if(front == NULL){
printf("\nQueue is Empty!!!\n");
}
else{
struct Node *temp = front;
front = front -> next;
if(front == NULL){
rear = NULL;
}
printf("\nDeleted element: %d\n", temp -> data);
free(temp);
}
}
9
1.7 Implement Queue using Stacks
A queue can be implemented using two stacks. There are two approaches to implement Queue using Stack:
• Making a enqueue operation costly - time complexity of enqueue operation will be O(n) and the time
complexity in dequeue operation would be O(1).
• Making a dequeue operation costly - time complexity of dequeue operation will be O(n) and the time
complexity in enqueue operation would be O(1).
– Pushing an element to the rear of the queue is the same as pushing it to the bottom of stack stack1.
– First all the elements will be popped from the stack1 and push it into the stack2.
– Once all the elements from the stack1 are pushed into the stack2, then the new element is pushed in the
stack1.
– After adding the new element in the stack1, all the element are popped back from stack2 and pushed to
stack1.
– Here, the time complexity of enqueue operation would be O(n).
• Removing an element from the front of the queue is similar to removing the top of stack stack1.
• In stack1, the oldest element would be at the top of the stack, so time taken to perform a dequeue operation
would be O(1).
10
Figure 1.6: Queue
• In case of enqueue operation, the newly arrived element is always added on top of stack1 and the first
element is kept as front queue element, so enqueue operation takes O(1) time.
• In case of dequeue operation, we need to consider two stacks named as Stack1 and Stack2.
– First, we insert the elements in the Stack1 and then we remove all the elements from the Stack1.
– Once all the elements are popped from the Stack1 then they are added in the Stack2.
– The topmost element would be popped out from the Stack2 and then all the elements from the Stack2
are moved back to Stack1.
• Here, dequeue operation is performed two times on the data so time complexity is O(n).
11
Figure 1.8: Queue
12
1.7.3 Home Assignment - Queue
• Implement Queue using Stacks
– https://www.javatpoint.com/implementation-of-queue-using-stacks
• Implement a Stack using a single Queue
– https://www.javatpoint.com/implementation-of-stack-using-queue
13
1.8 Circular Queue (CQ)
• A circular queue is an extended version of a linear queue.
• A circular queue is a linear DS as it is also based on the FIFO (First In First Out) principle except that the
last position is connected to the first position in a circular queue that forms a circle.
• It is also known as a Ring Buffer.
14
1.8.2 Applications of Circular Queue
• Memory Management: The unused memory locations in the case of ordinary queues can be utilized in
circular queues.
• CPU Scheduling: Operating systems often maintain a queue of processes that are ready to execute or that
are waiting for a particular event to occur.
• Traffic system: In computer controlled traffic system, circular queues are used to switch on the traffic lights
one by one repeatedly as per the time set.
1.8.4 Implement Circular Queue using Array - How you can achieve circular incremen-
tation
• The circular incrementation is achievable with the help of the modulo division.
15
16
1.8.5 Enqueue in Circular Queue
• Step 1 - Check whether circular queue is Empty i.e then set both front and rear to 0 i.e front = rear = 0 and
queue[rear] = item.
• Step 2 - Else if (If it is FULL), i.e (rear + 1) % MaxSize == front, then display "Queue is FULL!!! Insertion
is not possible!!!" and terminate the function.
• Step 3 - Else, set rear = (rear + 1) % Maxsize and queue[rear] = item.
17
1.8.6 Dequeue in Circular Queue
• The CQ is empty or Underflow in one condition i.e. front == -1 and rear == -1
• If (front == rear), there is only one element
• When the only element is deleted, then front and rear are reset to -1 (front = rear = -1)
• Step 1 - Check whether queue is EMPTY i.e (front == -1 && rear == -1)
• Step 2 - If it is EMPTY, then display "Queue is EMPTY!!! Deletion is not possible!!!" and terminate the
function.
• Step 3 - Else If, there is only one element in a queue i.e (front == rear), then set front and rear are reset to -1
i.e (front = rear = -1).
• Step 4 - Else, set display the deleted element and set front = (front + 1) % MaxSize
void dequeue() {
// condition to check queue is empty
if(front == -1 && rear == -1) {
printf("\n Queue Underflow.");
}
// condition to check queue contains single element
else if (front == rear) {
printf("\n The dequeued element is %d", queue[front]);
front = -1;
rear = -1;
}
else {
printf("\n The dequeued element is %d", queue[front]);
front = (front + 1) % MaxSize;
}
}
18
1.8.7 Video Lectures for Circular Queue
• https://www.youtube.com/watch?v=dn01XST9-bI&list=PLdo5W4Nhv31bbKJzrsKfMpo_grxuLl8LU&
index=44
• https://www.youtube.com/watch?v=40Ttkii9NPA&list=PLdo5W4Nhv31bbKJzrsKfMpo_grxuLl8LU&
index=45
19
1.9 Double-Ended Queue (DQ) or Deque
• Deque is a linear data structure in which the insertion and deletion operations are performed from both
ends.
• In a sense, this hybrid linear structure provides all the capabilities of stacks and queues in a single data
structure.
• In deque, the insertion and deletion operation can be performed from one side. The stack follows the LIFO
rule in which both the insertion and deletion can be performed only from one end; therefore, we conclude
that deque can be considered as a stack.
• In deque, the insertion can be performed on one end, and the deletion can be done on another end. The queue
follows the FIFO rule in which the element is inserted on one end and deleted from another end. Therefore,
we conclude that the deque can also be considered as the queue.
20
1.9.1 Types of DQ
• Input-restricted queue
– The input-restricted queue means that some restrictions are applied to the insertion.
– In input-restricted queue, the insertion is applied to one end while the deletion is applied from both
the ends.
• Output-restricted queue
– The output-restricted queue means that some restrictions are applied to the deletion operation.
– In an output-restricted queue, the deletion can be applied only from one end, whereas the insertion
is possible from both ends.
21
1.9.5 Home Assignment - Deque
• Implementation of Deque using Circular Array
• Implement Stack and Queue using Deque
22
1.10 Self-Study
• Priority Queues - (Heap data structure provides an efficient implementation of priority queues.)
• https://www.javatpoint.com/ds-priority-queue
• https://www.programiz.com/dsa/priority-queue
• https://www.geeksforgeeks.org/priority-queue-set-1-introduction/
23
1.11 Priority Queue
• A Priority Queue is a particular type of data structure in which every element is assigned a priority.
• Elements with higher priorities are processed before those with lower ones.
• When you add an element to the queue, it is inserted in a position based on its priority value.
• For example, if you add an element with a high priority value to a priority queue, it may be inserted near the
front of the queue, while an element with a low priority value may be inserted near the back.
• In the event of similar priorities, elements are processed based on their existing order in the queue. If multiple
elements have the same priority, then elements are processed from the queue according to the FCFS principle.
24
• Ascending order priority queue:
– In ascending order priority queue, a lower priority number is given as a higher priority in a priority.
– For example, we take the numbers from 1 to 5 arranged in an ascending order like 1,2,3,4,5; therefore,
the smallest number, i.e., 1 is given as the highest priority in a priority queue.
25
1.11.3 Implementation of Priority Queue
Priority queue can be implemented using an array, a linked list, a heap data structure, or a binary search tree.
Among these data structures, heap data structure provides an efficient implementation of priority queues.
• The image above shows how it maintains the priority during insertion in a queue. But, if you carry the N
comparisons for each insertion, time-complexity will become O(n2 ).
• In general, implementing a priority queue using arrays is not an ideal approach.
26
1.11.3.2 Linked List Implementation of Priority Queue
• Consider a linked queue having 3 data elements 3, 17, 43, respectively. It arranges all these elements
according to priority.
• But, what if you have to insert a new node into the linked queue consisting of value 2? Since 2 is smaller
than the element at the front (head) node, insertion from the front will be more efficient.
• Additionally, it will allow you to have O(1) time-complexity during deletion.
• The diagram above shows how it will insert the new node consisting of elements in a linked queue.
• This particular scenario of insertion seems perfect as it doesn’t cost you more time. But what if the element
is significantly larger than all the nodes of a queue?
• For instance, say you want to insert a node consisting of element 45. Here, it will compare element 45 with
each element inside the queue. However, this insertion will cost you O(N).
• Representation of the linked queue below displays how it will insert element 45 in a priority queue.
27
• Binary heap and binary tree provide almost similar complexities. These approaches cost you O(logn) for
insertion and deletion and O(1) for peek operation.
28
1.12 Sample Questions
1. Define a priority queue and provide an example of its application.
2. Describe the conditions that indicate whether a circular queue is full or empty.
3. Provide a demonstration of creating, adding, deleting, and checking the status of a queue data structure using
suitable examples.
4. Define and explain a circular queue (CQ). Write a program (WAP) to create a circular queue and include a
function to print its elements in increasing order.
5. Discuss the implementation of a circular queue using an array. Detail the functions required for circular
queue operations.
6. Define the term "dequeue" and illustrate it with a relevant example.
7. Develop a C function to add and delete elements from a circular queue implemented using an array.
29