Step 2 of 5

40% Complete

Enqueue Operation

Learn how to add elements to a queue

The Enqueue Operation

The enqueue operation adds an element to the rear (end) of the queue. It's like a person joining the back of a line.

When implementing a queue, the enqueue operation is responsible for:

  • Adding a new element to the end of the queue
  • Updating the rear pointer (if applicable)
  • Increasing the size of the queue

Array-based Implementation

In an array-based implementation, the enqueue operation is straightforward. We simply add the new element to the end of the array.

Enqueue Operation (Array-based)
enqueue(element) {
// Add element to the end of the array
this.items.push(element);
return this; // For method chaining
}
Before enqueuing 50:
10
20
30
After enqueuing 50:
10
20
30
50

Key Points:

  • Time Complexity: O(1) - constant time
  • Always adds to the rear of the queue
  • Simple to implement using JavaScript's built-in array methods
  • May require resizing the array if it has a fixed capacity

Linked List-based Implementation

In a linked list-based implementation, we add a new node to the tail of the linked list.

Enqueue Operation (Linked List-based)
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedListQueue {
constructor() {
this.head = null; // Front of the queue
this.tail = null; // Rear of the queue
this.size = 0;
}
enqueue(value) {
const newNode = new Node(value);
// If queue is empty, set both head and tail to the new node
if (this.isEmpty()) {
this.head = newNode;
this.tail = newNode;
} else {
// Otherwise, add to the end and update tail
this.tail.next = newNode;
this.tail = newNode;
}
this.size++;
return this;
}
isEmpty() {
return this.size === 0;
}
}

Key Points:

  • Time Complexity: O(1) - constant time
  • Requires maintaining both head and tail pointers for efficiency
  • Special handling for the first element (when the queue is empty)
  • No capacity limitations (can grow as needed)

Circular Queue Implementation

In a circular queue, we use an array with front and rear pointers that wrap around to the beginning when they reach the end. This allows for more efficient use of space.

Enqueue Operation (Circular Queue)
class CircularQueue {
constructor(capacity = 5) {
this.items = new Array(capacity);
this.capacity = capacity;
this.front = 0;
this.rear = 0;
this.size = 0;
}
enqueue(element) {
// Check if queue is full
if (this.isFull()) {
throw new Error("Queue overflow");
// Alternatively, resize the queue
// this.resize();
}
// Add element at the rear position
this.items[this.rear] = element;
// Update rear (wrap around if necessary)
this.rear = (this.rear + 1) % this.capacity;
// Increment size
this.size++;
return this;
}
isFull() {
return this.size === this.capacity;
}
isEmpty() {
return this.size === 0;
}
}

Key Points:

  • Time Complexity: O(1) - constant time
  • Uses modulo arithmetic to wrap around the array
  • Requires tracking size separately from front and rear pointers
  • More efficient space utilization compared to simple array implementation
  • Needs to handle the queue being full

Edge Cases and Considerations

Queue Overflow

In fixed-size implementations, you need to handle the case when the queue is full. Options include:

  • Throw an error
  • Return a failure indicator
  • Resize the queue (dynamic array)
  • Implement a circular buffer

Performance Considerations

While the enqueue operation is typically O(1), there are some considerations:

  • Array resizing can occasionally cause O(n) operations
  • Memory allocation for new nodes in linked list implementations
  • Cache locality is better in array-based implementations

Practical Example

Let's see a complete example of a queue with the enqueue operation:

class Queue {
constructor() {
this.items = [];
}
// Add an element to the queue
enqueue(element) {
this.items.push(element);
return this;
}
// Check if the queue is empty
isEmpty() {
return this.items.length === 0;
}
// Get the size of the queue
size() {
return this.items.length;
}
}
// Usage example
const queue = new Queue();
console.log("Queue created. Is empty?", queue.isEmpty()); // true
queue.enqueue(10);
console.log("After enqueuing 10:", queue.items); // [10]
queue.enqueue(20).enqueue(30); // Method chaining
console.log("After enqueuing 20 and 30:", queue.items); // [10, 20, 30]
console.log("Queue size:", queue.size()); // 3

Check Your Understanding

Next Steps

Now that you understand how to add elements to a queue with the enqueue operation, let's move on to learning how to remove elements from a queue with the dequeue operation.