VOOZH about

URL: https://www.geeksforgeeks.org/dsa/efficiently-implement-k-queues-single-array/

⇱ Implement k Queues in a single array - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Implement k Queues in a single array

Last Updated : 20 Sep, 2025

Given two integers n and k. Implement k queues using a single array of size n. Multiple queue must share the same array space while supporting the following operations:

enqueue(qn, x): Adds the element x into the qn-th queue.
dequeue(qn): Removes the front element from the qn-th queue and return it. If the queue is empty, return -1.
isEmpty(qn): Checks if the qn-th queue is empty.

[Naive Approach] Dividing Array into k Segments - O(1) Time and O(n+k) Space

The idea is to divide the array of size n into k equal segments, each of size n/k. Each segment serves as dedicated storage for one of the k queues. To manage these queues, we maintain two arrays front and rear which track the beginning and end of each queue. Both are initialized to -1 to represent empty queues.

We use a circular array technique within each segment. This ensures that space is utilized optimally when elements are enqueued and dequeued.

  • Enqueue: When inserting an element into queue i, we update the rear pointer (with wrap-around support) and place the element at that position.
  • Dequeue: When removing an element from queue i, we return the element at the front position and move the front pointer forward, again considering wrap-around logic to reuse the allocated space effectively.

Output
1 1 1 1 10 20 40 30 -1 

Drawback:
The main limitation of above approach is that it allocates a fixed block of space for each queue, regardless of actual usage. If one queue requires more space than its allocated n/k slots while another queue remains underutilized, the extra unused space cannot be shared. This results in internal fragmentation some queues may overflow even when free space exists in other segments leading to inefficient memory utilization.

[Expected Approach] Using Space Optimized Method - O(1) Time and O(n+k) Space

Instead of dividing the array into fixed blocks for each queue, we let all queues share the same array dynamically. We keep a free list that tells us which slots in the array are free, so any queue can use them. This way, no space is wasted and all queues can grow as needed.

Following are the extra arrays used:

  1. front[]: This is of size k and stores indexes of front elements in all queues. front[i] = -1 indicates an empty queue.
  2. rear[]: This is of size k and stores indexes of rear elements in all queues. rear[i] = -1 indicates an empty queue.
  3. next[]: This is of size n and stores indexes of next item for the items in array arr[]. For queue elements, it points to the next queue element index and for free slots, it indicates the index of next free slot.

Working:

Initialization:

  • front[k] = rear[k] = -1 all queues empty.
  • next[n] links elements and manages free slots: next[i] = i+1, next[n-1] = -1.
  • freeIndex = 0 first free slot.

Enqueue(x, qn):

  • If freeIndex == -1, array is full return false.
  • Allocate i = freeIndex, update freeIndex = next[i].
  • If queue empty front[qn] = rear[qn] = i.
  • Else link to rear: next[rear[qn]] = i, then rear[qn] = i.
  • End of queue next[i] = -1.
  • Store value: arr[i] = x.

Dequeue(qn):

  • If front[qn] == -1, queue empty return -1.
  • Get front index: i = front[qn], update front[qn] = next[i].
  • If queue becomes empty rear[qn] = -1.
  • Return index to free list: next[i] = freeIndex, freeIndex = i.
  • Return arr[i].

The best part of this implementation is that any free slot in the array can be used by any queue. This avoids space wastage compared to fixed-segment allocation. Although it needs extra arrays (front[], rear[], next[]), the overhead is small because queue elements are usually large objects (e.g., employees, students, tasks).


Output
1 1 1 1 10 20 40 30 -1 
Comment
Article Tags: