Queue Implementation Using Array
The simplest way to build a queue is to back it with an array and track a front index and a rear index. As long as those two indices are updated correctly on every enqueue and dequeue, the array behaves like a proper FIFO queue.
How Does It Work?
The array never moves — only the two indices do. front marks the element that leaves next, rear marks the last one that arrived, and every operation is just an index update:
- An empty queue of capacity 5. Both pointers start at -1, which is how the code tells empty apart from holding one element at index 0.
- enqueue(10), enqueue(20), enqueue(30): front is set to 0 on the first insert, and rear steps forward with each one.
- dequeue() twice: 10 and 20 are returned and front moves to index 2. Nothing is shifted — which is what keeps dequeue O(1) — but slots 0 and 1 are now stranded.
- enqueue(40), enqueue(50): rear reaches index 4, the last slot. The check rear == capacity - 1 now reports the queue as full even though it only holds 3 of 5 elements.
Step 4 is the flaw in the plain array approach. Two perfectly good slots sit empty at the start, but front only ever moves right, so nothing can reach them again. You can reclaim them by shifting every element down on each dequeue — at which point dequeue costs O(n) instead of O(1) — or you can let rear wrap around to index 0 with modulo arithmetic, which is exactly what a circular queue does and why it is the version normally used in practice.
Implementation Steps
- Initialize an array of fixed size (for static implementation) or dynamic array
- Initialize two pointers: front (for dequeue) and rear (for enqueue), both set to -1 initially
- Implement boundary checks for overflow (full queue) and underflow (empty queue) conditions
- For circular queue implementation, use modulo arithmetic for pointer updates
Enqueue Algorithm
- Check if queue is full (if (rear == capacity - 1) for linear array)
- For empty queue, set both front and rear to 0
- For circular queue: rear = (rear + 1) % capacity
- Insert new element at items[rear]
- Increment size counter
Dequeue Algorithm
- Check if queue is empty (front == -1)
- Store the front element to return later
- If only one element (front == rear), reset pointers to -1
- For circular queue: front = (front + 1) % capacity
- Decrement size counter
- Return the stored element
Time & Space Complexity
- Enqueue Operation: O(1) - Amortized constant time for dynamic arrays
- Dequeue Operation: O(1) - No shifting needed with pointer approach
- Peek Operation: O(1) - Direct access via front pointer
- Space Usage: O(n) - Linear space for storing elements
Because both enqueue and dequeue only touch an index and a single slot, none of them get slower as the queue fills up:
Pros and Cons
- Pros: Simple implementation, cache-friendly (array elements contiguous in memory)
- Pros: Efficient O(1) operations with pointer tracking
- Cons: Fixed size limitation in static array implementation
- Cons: Wasted space in linear array implementation without circular approach
Practical Considerations
The catch with a plain array is wasted space at the front once you've dequeued a few elements: the circular-array trick fixes that by letting the rear index wrap back around to index 0 once it hits the end.
Queues are widely used in scenarios like printer job scheduling, call center systems, and network packet handling where order preservation is crucial.