Queue Data Structure: Introduction

Learn Queue Data Structure: Introduction with practical examples, explanations, best practices, and real-world coding techniques.

What Is a Queue?

A queue is a linear data structure that stores elements in a specific order and processes them according to the FIFO (First In, First Out) principle. The element that enters the queue first is normally the first element to be removed.

A simple real-world example is a line of people waiting at a service counter. The person who arrives first is generally served first, while newly arriving people join the end of the line. A queue data structure follows the same basic idea.

Queue order:

Front → [ 10 ] [ 20 ] [ 30 ] [ 40 ] ← Rear

Remove → 10
Add    → 50

After adding 50:
Front → [ 20 ] [ 30 ] [ 40 ] [ 50 ] ← Rear

Understanding FIFO

FIFO stands for First In, First Out. It describes the order in which elements are processed. If several elements are added to a queue, they are removed in the same order in which they were inserted.

For example, if the values 10, 20, and 30 are inserted into a queue, the removal order will be 10, then 20, and finally 30.

Operation Queue Result
Enqueue 10 10 10 enters first
Enqueue 20 10, 20 20 joins the rear
Enqueue 30 10, 20, 30 30 joins the rear
Dequeue 20, 30 10 is removed first

Front and Rear of a Queue

A queue normally has two important positions: the front and the rear. The front identifies the element that is next to be removed, while the rear identifies where a new element is added.

                Queue
                  ↓

Front → [ 15 ] [ 25 ] [ 35 ] [ 45 ] ← Rear
          ↑                         ↑
      Remove here               Add here

Maintaining these two ends makes the queue concept different from structures where elements can be freely inserted or removed from arbitrary positions.

Basic Queue Operations

A queue provides a small set of core operations for adding, removing, and inspecting elements.

  • Enqueue: Adds an element to the rear of the queue.
  • Dequeue: Removes the element from the front of the queue.
  • Peek: Returns the front element without removing it.
  • IsEmpty: Determines whether the queue contains any elements.
  • Size: Returns the number of elements currently stored.

Enqueue

Enqueue is the operation used to add a new element to the rear of a queue. Existing elements remain in their current order.

Queue: [10] [20] [30]

Enqueue(40)

Queue: [10] [20] [30] [40]

The new value is placed after the current last element. This preserves FIFO ordering.

Dequeue

Dequeue removes the element at the front of the queue. This is the operation that enforces the first-in, first-out behavior.

Queue: [10] [20] [30]

Dequeue()

Queue: [20] [30]

Removed: 10

A dequeue operation on an empty queue requires special handling. Depending on the implementation, it may return a special value, throw an exception, or otherwise indicate that no element is available.

Queue vs Stack

Queues and stacks are both linear data structures, but they process elements in different orders. A queue follows FIFO, while a stack follows LIFO (Last In, First Out).

Feature Queue Stack
Ordering FIFO LIFO
Insertion Rear Top
Removal Front Top
Typical use Scheduling and processing in arrival order Undo, backtracking, function calls

How a Queue Can Be Implemented

A queue is an abstract data structure, so its behavior can be implemented using different underlying structures. Common implementations include arrays, linked lists, and language-provided queue collections.

When an array is used, the implementation must be designed carefully. Removing the first element from a basic array by shifting every remaining element can take O(n) time. A more efficient implementation can maintain a front index so that elements do not need to be shifted after every dequeue operation.

const queue = [];
let front = 0;

queue.push(10);
queue.push(20);
queue.push(30);

const first = queue[front];
front++;

console.log(first); // 10
console.log(queue[front]); // 20

Where Queues Are Used

Queues are useful whenever work needs to be processed in an ordered sequence, especially when the earliest waiting item should normally be handled first.

  • Task scheduling: Processes waiting tasks in an ordered manner.
  • Print systems: Manages documents waiting to be printed.
  • Request processing: Stores requests waiting for server-side processing.
  • Message systems: Holds messages until they can be consumed.
  • Breadth-first search: Stores graph or tree nodes that need to be processed level by level.
  • Event processing: Maintains events waiting for a system or component to handle them.

Queue in Breadth-First Search

One of the most important algorithmic uses of a queue is Breadth-First Search (BFS). BFS visits nodes level by level. A queue stores nodes that have been discovered but have not yet been processed.

Start
  ↓
Queue: [A]

Remove A → add its neighbors
Queue: [B, C]

Remove B → add its unvisited neighbors
Queue: [C, D, E]

Because nodes are processed in the order they are added, the FIFO behavior of a queue naturally supports level-order traversal.

Advantages of Queues

  • Provides a clear FIFO processing model.
  • Useful for managing waiting tasks and requests.
  • Works naturally with breadth-first traversal algorithms.
  • Can provide efficient insertion and removal when implemented correctly.
  • Helps separate producers that generate work from consumers that process it.

Things to Consider

The word "queue" describes the behavior, not necessarily one specific implementation. The performance of a queue depends on how it is implemented.

For example, repeatedly removing the first element from a normal JavaScript array using shift() can require elements to be reindexed or moved. For large queues, a head index, linked-list implementation, or dedicated queue structure can avoid unnecessary work.

Queue Complexity

With an appropriate queue implementation, enqueue and dequeue operations are commonly designed to run in O(1) time. The exact complexity depends on the underlying implementation.

Operation Typical Complexity Purpose
Enqueue O(1) Add an element to the rear
Dequeue O(1) Remove the front element
Peek O(1) Read the front element
Search O(n) Find a specific element

Queue Example in JavaScript

The following example uses an array together with a front index. This avoids repeatedly removing the first array element and demonstrates the basic FIFO behavior of a queue.

const queue = [];
let front = 0;

function enqueue(value) {
  queue.push(value);
}

function dequeue() {
  if (front >= queue.length) {
    return null;
  }

  const value = queue[front];
  front++;

  return value;
}

function peek() {
  return front < queue.length ? queue[front] : null;
}

enqueue("Task 1");
enqueue("Task 2");
enqueue("Task 3");

console.log(dequeue()); // Task 1
console.log(peek());    // Task 2

In a production implementation, additional logic can be used to periodically compact the array after many dequeue operations. The important concept here is that the front position moves forward while new elements continue to enter at the rear.

When Should You Use a Queue?

A queue is a natural choice when the order in which items arrive matters and earlier items should generally be processed before later items.

Common signals that a queue may be appropriate include:

  • Items need to be processed in arrival order.
  • Tasks are waiting for an available worker or resource.
  • Requests need to be processed sequentially.
  • An algorithm needs level-by-level traversal.
  • There is a producer-consumer workflow.

Key Takeaways

  • A queue is a linear data structure based on the FIFO principle.
  • Elements are normally added at the rear and removed from the front.
  • Enqueue adds an element, while dequeue removes an element.
  • Peek reads the front element without removing it.
  • Queues are widely used in scheduling, request processing, messaging, and BFS.
  • The performance of queue operations depends on the implementation.
  • An efficient queue can provide constant-time enqueue and dequeue operations.

Code Examples

const queue = [];
let front = 0;

function enqueue(value) {
  queue.push(value);
}

function dequeue() {
  if (front >= queue.length) {
    return null;
  }

  return queue[front++];
}

enqueue(10);
enqueue(20);
enqueue(30);

console.log(dequeue()); // 10
console.log(dequeue()); // 20
console.log(queue[front]); // 30
    
const queue = [];
let front = 0;

queue.push("A");
queue.push("B");
queue.push("C");

function peek() {
  return front < queue.length
    ? queue[front]
    : null;
}

console.log(peek()); // A

front++;

console.log(peek()); // B
    
const tasks = [
  "Load user profile",
  "Fetch notifications",
  "Generate report"
];

let front = 0;

while (front < tasks.length) {
  const task = tasks[front++];
  console.log("Processing:", task);
}

// Processing: Load user profile
// Processing: Fetch notifications
// Processing: Generate report
    

Pro Tip

When implementing a queue with a JavaScript array, avoid repeatedly using shift() for large workloads. A front index or dedicated queue structure can provide more efficient FIFO operations.

🎨 IgKnight Docs

Master HTML, CSS, JS, Python, .NET and more with easy-to-follow lessons and practical code examples.

© 2025 IgKnight Learning Platform. All rights reserved.