Queue
Queue in Data Structures
Learn what a queue is, how queue works using the FIFO principle, important queue operations such as enqueue, dequeue, front, rear, and isEmpty, and how queues are used in real-world programming problems like ticket counters, task scheduling, printer queues, CPU scheduling, and message processing.
Introduction
A queue is an important linear data structure in programming. It stores data in a special order where the first item added is the first item removed. This rule is known as FIFO, which means First In, First Out.
A queue is very common in real life. For example, when people stand in a line at a ticket counter, the person who comes first gets served first. The person who joins later must wait behind others. This same idea is used in programming through a queue.
Queues are used when data or tasks must be processed in the same order in which they arrive. They are commonly used in operating systems, printers, customer service systems, networking, message queues, CPU scheduling, and background task processing.
Simple Definition of Queue
A queue is a data structure where elements are inserted from one end and removed from the other end. The insertion end is usually called the rear, and the removal end is called the front.
In simple words:
- A queue stores elements in order.
- The first inserted element is removed first.
- New elements are added at the rear end.
- Elements are removed from the front end.
- Queue follows the FIFO rule.
- Queue is useful for waiting-line and scheduling problems.
Why Do We Need Queue?
Queues are needed when items must be processed in the order they arrive. Many real-world systems require fairness and order. If a person or task arrives first, it should be processed first.
For example, in a printer queue, documents are printed in the order they are submitted. If three people send documents to the printer, the first submitted document should print first, then the second, then the third. This is queue behavior.
Without Queue
- Tasks may be processed randomly.
- First-come-first-served order may not be maintained.
- Scheduling can become unfair.
- Printer jobs may be handled incorrectly.
- Customer requests may become disorganized.
- Message processing can become unreliable.
With Queue
- Tasks are processed in arrival order.
- First-come-first-served logic becomes easy.
- Scheduling becomes fair and organized.
- Printer jobs can be managed correctly.
- Customer requests are handled systematically.
- Messages can be processed in sequence.
Prerequisites
Before learning queues, students should understand some basic programming and data structure concepts. These topics make queue operations easier to understand.
| Prerequisite Topic | Why It Is Needed |
|---|---|
| Variables | To store queue values and front/rear positions. |
| Arrays / Lists | Queues can be implemented using arrays or lists. |
| Linked Lists | Queues can also be implemented using linked lists. |
| Loops | Used to display or process queue elements. |
| Conditional Statements | Used to check empty, full, overflow, and underflow conditions. |
| Functions / Methods | Queue operations are usually written as methods such as enqueue() and dequeue(). |
| Stack Concept | Helps compare LIFO and FIFO behavior clearly. |
Real-World Analogy of Queue
The easiest real-world example of a queue is a line of people waiting at a ticket counter. The person who joins the line first gets the ticket first. New people join at the end of the line, and service happens from the front of the line.
This is exactly how a queue works in programming. New elements are added at the rear, and elements are removed from the front.
Queue as a Waiting Line
A queue works like a line at a ticket counter. The first person in the line is served first, and new people join at the end.
| Real-World Example | Queue Concept | Explanation |
|---|---|---|
| Ticket counter line | FIFO | The first person in line is served first. |
| Printer queue | Job scheduling | The first submitted print job prints first. |
| Customer support queue | Request handling | Customer requests are handled in arrival order. |
| Food delivery order queue | Order processing | Orders can be processed based on arrival sequence. |
FIFO Principle
The most important rule of a queue is FIFO. FIFO stands for First In, First Out. This means the first element inserted into the queue will be the first element removed from the queue.
Suppose we insert elements in this order:
Enqueue 10
Enqueue 20
Enqueue 30
The queue will look like this:
Front -> 10 20 30 <- Rear
If we remove an element, 10 will be removed first because it was inserted first.
Front and Rear
A queue has two important ends:
- Front: The end from where elements are removed.
- Rear: The end where new elements are inserted.
Front -> 10 20 30 <- Rear
In this example, 10 is at the front and 30 is at the rear.
Basic Queue Operations
A queue supports several basic operations. These operations are used to add, remove, view, and check queue elements.
| Operation | Meaning | Example |
|---|---|---|
| enqueue() | Adds an element to the rear of the queue. | enqueue(10) |
| dequeue() | Removes an element from the front of the queue. | dequeue() |
| front() / peek() | Returns the front element without removing it. | front() |
| rear() | Returns the rear element without removing it. | rear() |
| isEmpty() | Checks whether the queue is empty. | isEmpty() |
| isFull() | Checks whether a fixed-size queue is full. | isFull() |
| display() | Displays all queue elements. | display() |
Enqueue Operation
The enqueue operation adds a new element to the rear of the queue. After enqueue, the newly added element becomes the rear element.
// Conceptual enqueue operation
enqueue(10)
enqueue(20)
enqueue(30)
Queue after these operations:
Front -> 10 20 30 <- Rear
Dequeue Operation
The dequeue operation removes the front element from the queue. After dequeue, the next element becomes the new front.
// Before dequeue
Front -> 10 20 30 <- Rear
dequeue()
// After dequeue
Front -> 20 30 <- Rear
In this example, 10 is removed because it was at the front.
Front / Peek Operation
The front or peek operation returns the front element of the queue without removing it.
// Queue
Front -> 10 20 30 <- Rear
front() returns 10
After front(), the queue remains unchanged.
isEmpty Operation
The isEmpty operation checks whether the queue has no elements. This is important before performing dequeue or front operations.
// Conceptual isEmpty
if queue is empty:
print "Queue is empty"
else:
print "Queue has elements"
Queue Overflow and Underflow
In queue operations, two common error conditions are overflow and underflow.
| Condition | Meaning | When It Happens |
|---|---|---|
| Queue Overflow | Trying to enqueue into a full queue. | Fixed-size queue has no more space. |
| Queue Underflow | Trying to dequeue from an empty queue. | No element exists to remove. |
Queue Overflow
- Occurs during enqueue operation.
- Happens when a fixed-size queue is full.
- Can be avoided by checking isFull().
Queue Underflow
- Occurs during dequeue or front operation.
- Happens when the queue is empty.
- Can be avoided by checking isEmpty().
Queue Conceptual Implementation
A queue can be implemented using an array, list, or linked list. The following conceptual example shows basic queue logic.
// Conceptual queue operations
queue = empty list
enqueue(value):
add value at rear of queue
dequeue():
if queue is empty:
print "Queue underflow"
else:
remove value from front
front():
if queue is empty:
print "Queue is empty"
else:
return front value
Java Example: Queue Using Array
The following Java example shows a simple queue implementation using an array.
class Queue {
int[] queue;
int front;
int rear;
int size;
Queue(int queueSize) {
size = queueSize;
queue = new int[size];
front = 0;
rear = -1;
}
void enqueue(int value) {
if (rear == size - 1) {
System.out.println("Queue overflow");
} else {
rear++;
queue[rear] = value;
System.out.println(value + " added to queue");
}
}
void dequeue() {
if (front > rear) {
System.out.println("Queue underflow");
} else {
System.out.println(queue[front] + " removed from queue");
front++;
}
}
void peek() {
if (front > rear) {
System.out.println("Queue is empty");
} else {
System.out.println("Front element: " + queue[front]);
}
}
void display() {
if (front > rear) {
System.out.println("Queue is empty");
} else {
System.out.println("Queue elements:");
for (int i = front; i <= rear; i++) {
System.out.println(queue[i]);
}
}
}
}
public class Main {
public static void main(String[] args) {
Queue queue = new Queue(5);
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
queue.peek();
queue.display();
queue.dequeue();
queue.display();
}
}
In this example, rear tracks where new elements are added, and front tracks where elements are removed.
JavaScript Example: Queue Using Array
JavaScript arrays can be used to implement a simple queue. The push() method adds an element at the rear, and the shift() method removes an element from the front.
class Queue {
constructor() {
this.items = [];
}
enqueue(value) {
this.items.push(value);
console.log(value + " added to queue");
}
dequeue() {
if (this.isEmpty()) {
console.log("Queue underflow");
} else {
const removedValue = this.items.shift();
console.log(removedValue + " removed from queue");
}
}
peek() {
if (this.isEmpty()) {
console.log("Queue is empty");
} else {
console.log("Front element: " + this.items[0]);
}
}
isEmpty() {
return this.items.length === 0;
}
display() {
if (this.isEmpty()) {
console.log("Queue is empty");
} else {
console.log("Queue elements:");
for (let i = 0; i < this.items.length; i++) {
console.log(this.items[i]);
}
}
}
}
const queue = new Queue();
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
queue.peek();
queue.display();
queue.dequeue();
queue.display();
This JavaScript example shows how a queue can be implemented using an array internally.
Queue Using Linked List
A queue can also be implemented using a linked list. In a linked-list-based queue, new nodes are added at the rear, and nodes are removed from the front.
Linked-list-based queues can grow dynamically because nodes are created as needed.
Queue Using Array vs Linked List
| Basis | Array-Based Queue | Linked-List-Based Queue |
|---|---|---|
| Size | May be fixed. | Can grow dynamically. |
| Memory | Uses continuous memory in many languages. | Uses nodes stored separately. |
| Overflow | Can occur if fixed-size queue becomes full. | Less likely unless memory is unavailable. |
| Implementation | Usually simpler for beginners. | Requires node and link management. |
| Best Use | When maximum size is known. | When size changes frequently. |
Problem with Simple Array Queue
In a simple array-based queue, every time an element is removed, the front moves forward. After several dequeue operations, empty spaces may appear at the beginning of the array.
Even if there is free space at the front, the queue may appear full because the rear has reached the last index. This problem can be solved using a circular queue.
Circular Queue
A circular queue is an improved version of a queue where the last position is connected back to the first position. This allows unused spaces to be reused.
Circular queues are useful when queue size is fixed but we want to use available space efficiently.
Types of Queues
Queues can be of different types depending on how insertion and deletion are allowed.
Simple Queue
Follows basic FIFO order
Elements are inserted at the rear and removed from the front.
Circular Queue
Last position connects back to first position
It uses fixed-size storage more efficiently by reusing empty spaces.
Priority Queue
Elements are processed based on priority
Higher-priority elements may be removed before lower-priority elements.
Deque
Double-ended queue
Insertion and deletion can happen from both front and rear ends.
Types of Queues Comparison
| Queue Type | Main Rule | Example Use |
|---|---|---|
| Simple Queue | First In, First Out | Ticket counter line |
| Circular Queue | Rear wraps around to front | Fixed-size buffer |
| Priority Queue | Highest priority processed first | Emergency hospital system |
| Deque | Insertion and deletion from both ends | Advanced scheduling and sliding window problems |
Real-World Example: Printer Queue
A printer queue is a common example of queue behavior. When multiple users send documents to a printer, the documents are stored in a queue. The first document sent is printed first.
Printer Queue:
Front -> Document 1 Document 2 Document 3 <- Rear
Document 1 will be printed first, then Document 2, then Document 3.
Real-World Example: Customer Support Queue
In customer support systems, customer requests are often handled using a queue. The first customer who raises a request should usually be served first.
Support Queue:
Front -> Customer A Customer B Customer C <- Rear
Customer A is handled first because Customer A entered the queue first.
Real-World Example: CPU Scheduling
Operating systems use queues to manage processes waiting for CPU time. Processes can be placed in a ready queue and processed according to scheduling rules.
In simple first-come-first-served scheduling, the process that enters the queue first is executed first.
Real-World Example: Message Queue
Message queues are used in software systems where one part of an application sends messages and another part processes them. Messages can be processed in the order they arrive.
This is useful in background processing, notification systems, order processing, and distributed systems.
Common Applications of Queue
| Application | How Queue is Used |
|---|---|
| Printer Queue | Print jobs are processed in order. |
| Ticket Booking System | Users are served based on arrival order. |
| Customer Support System | Requests are handled in sequence. |
| CPU Scheduling | Processes wait for CPU time in a queue. |
| Message Queue | Messages are processed in arrival order. |
| Network Data Packets | Packets may wait in queues before processing. |
| Breadth-First Search | Graph and tree traversal can use a queue. |
| Task Scheduling | Tasks are managed according to waiting order. |
Advantages of Queue
Queues are simple and powerful when data must be processed in arrival order.
Benefits of Queue
- Simple and easy to understand.
- Follows a clear FIFO rule.
- Useful for fair processing.
- Maintains order of arrival.
- Useful in scheduling systems.
- Useful in printer and task queues.
- Helps manage waiting lists.
- Can be implemented using arrays or linked lists.
- Useful in graph traversal such as breadth-first search.
- Supports real-world systems like messaging and order processing.
Limitations of Queue
Queues are useful, but they are not suitable for every problem. Queue access is limited mainly to front and rear operations.
Queue vs Stack
Queue and stack are both linear data structures, but they follow opposite processing rules. Stack follows LIFO, while queue follows FIFO.
| Basis | Queue | Stack |
|---|---|---|
| Rule | First In, First Out | Last In, First Out |
| Insertion | At rear | At top |
| Deletion | From front | From top |
| Real-World Example | Line at ticket counter | Stack of plates |
| Use Case | Scheduling, waiting lines, task processing | Undo, recursion, backtracking |
When Should You Use Queue?
Queue should be used when the first item that arrives should be processed first. If a problem requires first-come-first-served behavior, queue is often a good choice.
Use Queue When
- You need First In, First Out behavior.
- You need to manage waiting lines.
- You need fair task processing.
- You need printer job scheduling.
- You need CPU or process scheduling.
- You need message processing in arrival order.
- You need breadth-first search.
- You need to process customer requests sequentially.
Common Mistakes Beginners Make
Beginners often confuse queue with stack. Understanding FIFO clearly helps avoid mistakes.
Common Mistakes
- Confusing queue with stack.
- Forgetting that queue follows FIFO.
- Trying to remove elements from the rear in a simple queue.
- Trying to insert elements at the front in a simple queue.
- Not checking if queue is empty before dequeue.
- Not checking if fixed-size queue is full before enqueue.
- Confusing front with rear.
- Not understanding space wastage in simple array queue.
Better Approach
- Remember FIFO: First In, First Out.
- Enqueue adds at rear.
- Dequeue removes from front.
- Peek only reads the front element.
- Check isEmpty() before dequeue or peek.
- Check isFull() for fixed-size queue.
- Use diagrams to trace queue operations.
- Learn circular queue after simple queue.
Best Practices for Learning Queue
Queue becomes easy when students understand the FIFO rule and practice enqueue and dequeue operations visually.
Recommended Practices
- Start with real-world examples like ticket counter lines.
- Draw queue diagrams before writing code.
- Understand front and rear clearly.
- Practice enqueue operation step by step.
- Practice dequeue operation step by step.
- Understand the difference between queue and stack.
- Check empty queue condition before removing values.
- Implement queue using array first.
- Then understand queue using linked list.
- Learn circular queue after understanding simple queue.
Mini Practice Activity
Complete the following practice tasks to strengthen your understanding of queues.
| Task | Description | Expected Learning |
|---|---|---|
| Task 1 | Draw a queue after enqueueing 10, 20, and 30. | Understand enqueue and rear position. |
| Task 2 | Perform one dequeue operation and draw the queue again. | Understand dequeue and front position. |
| Task 3 | Write the result of front() after enqueueing 5, 15, and 25. | Understand front element access. |
| Task 4 | Explain queue overflow with an example. | Understand fixed-size queue limitation. |
| Task 5 | Explain queue underflow with an example. | Understand empty queue condition. |
| Task 6 | Give three real-world examples of queue behavior. | Connect queue with real life. |
Frequently Asked Questions
1. What is a queue?
A queue is a linear data structure that follows the First In, First Out principle. The first element added is the first element removed.
2. What does FIFO mean?
FIFO means First In, First Out. It means the earliest inserted element is removed first.
3. What is enqueue operation?
Enqueue is the operation of adding a new element to the rear of the queue.
4. What is dequeue operation?
Dequeue is the operation of removing an element from the front of the queue.
5. What is front in a queue?
Front is the end from where elements are removed. It points to the first element waiting to be processed.
6. What is rear in a queue?
Rear is the end where new elements are inserted.
7. What is queue overflow?
Queue overflow occurs when we try to add an element to a full fixed-size queue.
8. What is queue underflow?
Queue underflow occurs when we try to remove an element from an empty queue.
9. What is the difference between queue and stack?
A queue follows FIFO, meaning first inserted is first removed. A stack follows LIFO, meaning last inserted is first removed.
10. Where is queue used in real life?
Queue is used in ticket counters, printer queues, customer support systems, CPU scheduling, message queues, task scheduling, and breadth-first search.
Summary
A queue is a linear data structure that follows the FIFO principle, which means First In, First Out. Elements are inserted at the rear and removed from the front.
The main queue operations are enqueue, dequeue, front or peek, rear, isEmpty, isFull, and display. Enqueue adds an element to the rear, dequeue removes an element from the front, and front returns the first element without removing it.
Queues are used in many important areas of programming and real-world systems, including printer queues, ticket counters, customer support systems, CPU scheduling, message queues, task scheduling, and breadth-first search.
Key Takeaway
A queue is a linear data structure that follows the FIFO rule: First In, First Out. It is useful when the first item that arrives must be processed first, such as in ticket counters, printer queues, task scheduling, and message processing systems.