implement k Queues in a single array (original) (raw)
Last Updated : 27 Apr, 2025
**Given an array of size **n, the task is to implement **k queues using the array.
**enqueue(qn, x) : Adds the element x into the queue number qn
**dequeue(qn, x) : Removes the front element from queue number qn
**isFull(qn) : Checks if the queue number qn is full
**isEmpty(qn) : Checks if the queue number qn is empty.
**Naive Approach - Dividing Array into k Segments
The idea is to divide the array of size n into k equal segments, each of size n/k. Each segment acts as a dedicated space for one of the k queues. We maintain two arrays, front and rear, to track the beginning and end of each queue. Both are initialized to -1 to indicate empty queues. Please remember, to implement queue using array efficiently, we need to use circular array implementation, we use the same for every individual queue.
When enqueuing an element to queue i, we update the rear pointer and add the element at that position, considering wrap-around within that queue's segment. For dequeuing from queue i, we return the element at the front position and increment the front pointer, again with wrap-around logic to efficiently use the allocated space.
**Problem with this approach? The main drawback is that it allocates a fixed amount of space for each queue regardless of their actual usage. If one queue requires more space than its allocated n/k elements while another queue is mostly empty, we still can't use the empty space from one queue for the overflow of another. This leads to "internal fragmentation" where some queues might overflow even though there's plenty of unused space in the array overall, making poor use of the available memory.
C++ `
// C++ program to implement k queues // in a single array (Naive Approach) #include <bits/stdc++.h> using namespace std;
class kQueues {
private:
vector arr;
int n, k;
vector front;
vector rear;
public: kQueues(int n, int k) { this->n = n; this->k = k; arr.resize(n); front.resize(k, -1); rear.resize(k, -1); }
// Function to check if queue 'qn' is empty
bool isEmpty(int qn) {
return (front[qn] == -1);
}
// Function to check if queue 'qn' is full
bool isFull(int qn) {
// Calculate the next position after rear
int nextPos = (rear[qn] + 1) % (n/k);
// Queue is full if next position is front
return (nextPos == front[qn] % (n/k) && front[qn] != -1);
}
// Function to enqueue 'x' into queue 'qn'
bool enqueue(int x, int qn) {
// Check if queue is full
if (isFull(qn))
return false;
// Calculate the base index for this queue
int base = qn * (n/k);
// For empty queue, set front index
if (isEmpty(qn))
front[qn] = base;
// Update rear and add element
rear[qn] = (rear[qn] == -1) ?
base :
base + (rear[qn] + 1 - base) % (n/k);
arr[rear[qn]] = x;
return true;
}
// Function to dequeue from queue 'qn'
int dequeue(int qn) {
// Check if queue is empty
if (isEmpty(qn))
return -1;
// Get the base index for this queue
int base = qn * (n/k);
// Get the element to be dequeued
int x = arr[front[qn]];
// If this is the last element, reset front and rear
if (front[qn] == rear[qn]) {
front[qn] = -1;
rear[qn] = -1;
} else {
// Move front to next position,
// considering wrap-around within segment
front[qn] = base + (front[qn] + 1 - base) % (n/k);
}
return x;
}
};
int main() { int n = 10, k = 3; kQueues queues(n, k);
cout << queues.enqueue(10, 0) << " ";
cout << queues.enqueue(20, 1) << " ";
cout << queues.enqueue(30, 0) << " ";
cout << queues.enqueue(40, 2) << " ";
cout << queues.dequeue(0) << " ";
cout << queues.dequeue(1) << " ";
cout << queues.dequeue(2) << " ";
cout << queues.dequeue(0) << " ";
cout << queues.dequeue(0) << " ";
return 0;
}
Java
// Java program to implement k queues // in a single array (Naive Approach) import java.util.*;
class kQueues {
int[] arr;
int n, k;
int[] front;
int[] rear;
kQueues(int n, int k) {
this.n = n;
this.k = k;
arr = new int[n];
front = new int[k];
rear = new int[k];
Arrays.fill(front, -1);
Arrays.fill(rear, -1);
}
// Function to check if queue 'qn' is empty
static boolean isEmpty(int[] front, int qn) {
return (front[qn] == -1);
}
// Function to check if queue 'qn' is full
static boolean isFull(int[] front, int[] rear, int qn, int n, int k) {
// Calculate the next position after rear
int nextPos = (rear[qn] + 1) % (n/k);
// Queue is full if next position is front
return (nextPos == front[qn] % (n/k) && front[qn] != -1);
}
// Function to enqueue 'x' into queue 'qn'
boolean enqueue(int x, int qn) {
if (isFull(front, rear, qn, n, k))
return false;
int base = qn * (n/k);
if (isEmpty(front, qn))
front[qn] = base;
rear[qn] = (rear[qn] == -1) ?
base :
base + (rear[qn] + 1 - base) % (n/k);
arr[rear[qn]] = x;
return true;
}
// Function to dequeue from queue 'qn'
int dequeue(int qn) {
if (isEmpty(front, qn))
return -1;
int base = qn * (n/k);
int x = arr[front[qn]];
if (front[qn] == rear[qn]) {
front[qn] = -1;
rear[qn] = -1;
} else {
front[qn] = base + (front[qn] + 1 - base) % (n/k);
}
return x;
}
}
class GfG { public static void main(String[] args) { int n = 10, k = 3; kQueues queues = new kQueues(n, k);
System.out.print(queues.enqueue(10, 0) + " ");
System.out.print(queues.enqueue(20, 1) + " ");
System.out.print(queues.enqueue(30, 0) + " ");
System.out.print(queues.enqueue(40, 2) + " ");
System.out.print(queues.dequeue(0) + " ");
System.out.print(queues.dequeue(1) + " ");
System.out.print(queues.dequeue(2) + " ");
System.out.print(queues.dequeue(0) + " ");
System.out.print(queues.dequeue(0) + " ");
}
}
Python
Python program to implement k queues
in a single array (Naive Approach)
class kQueues: def init(self, n, k): self.n = n self.k = k self.arr = [0] * n self.front = [-1] * k self.rear = [-1] * k
# Function to check if queue 'qn' is empty
def isEmpty(self, qn):
return self.front[qn] == -1
# Function to check if queue 'qn' is full
def isFull(self, qn):
nextPos = (self.rear[qn] + 1) % (self.n // self.k)
return (nextPos == self.front[qn] % (self.n // self.k) and self.front[qn] != -1)
# Function to enqueue 'x' into queue 'qn'
def enqueue(self, x, qn):
if self.isFull(qn):
return False
base = qn * (self.n // self.k)
if self.isEmpty(qn):
self.front[qn] = base
self.rear[qn] = base if self.rear[qn] == -1 \
else base + (self.rear[qn] + 1 - base) % (self.n // self.k)
self.arr[self.rear[qn]] = x
return True
# Function to dequeue from queue 'qn'
def dequeue(self, qn):
if self.isEmpty(qn):
return -1
base = qn * (self.n // self.k)
x = self.arr[self.front[qn]]
if self.front[qn] == self.rear[qn]:
self.front[qn] = -1
self.rear[qn] = -1
else:
self.front[qn] = base + (self.front[qn] + 1 - base) % (self.n // self.k)
return x
if name == "main": n, k = 10, 3 queues = kQueues(n, k)
print(queues.enqueue(10, 0), end=" ")
print(queues.enqueue(20, 1), end=" ")
print(queues.enqueue(30, 0), end=" ")
print(queues.enqueue(40, 2), end=" ")
print(queues.dequeue(0), end=" ")
print(queues.dequeue(1), end=" ")
print(queues.dequeue(2), end=" ")
print(queues.dequeue(0), end=" ")
print(queues.dequeue(0), end=" ")
C#
// C# program to implement k queues // in a single array (Naive Approach) using System;
class kQueues {
int[] arr;
int n, k;
int[] front;
int[] rear;
public kQueues(int n, int k) {
this.n = n;
this.k = k;
arr = new int[n];
front = new int[k];
rear = new int[k];
for (int i = 0; i < k; i++) {
front[i] = -1;
rear[i] = -1;
}
}
// Function to check if queue 'qn' is empty
static bool isEmpty(int[] front, int qn) {
return (front[qn] == -1);
}
// Function to check if queue 'qn' is full
static bool isFull(int[] front, int[] rear, int qn, int n, int k) {
int nextPos = (rear[qn] + 1) % (n / k);
return (nextPos == front[qn] % (n / k) && front[qn] != -1);
}
// Function to enqueue 'x' into queue 'qn'
public bool enqueue(int x, int qn) {
if (isFull(front, rear, qn, n, k))
return false;
int baseIndex = qn * (n / k);
if (isEmpty(front, qn))
front[qn] = baseIndex;
rear[qn] = (rear[qn] == -1) ?
baseIndex :
baseIndex + (rear[qn] + 1 - baseIndex) % (n / k);
arr[rear[qn]] = x;
return true;
}
// Function to dequeue from queue 'qn'
public int dequeue(int qn) {
if (isEmpty(front, qn))
return -1;
int baseIndex = qn * (n / k);
int x = arr[front[qn]];
if (front[qn] == rear[qn]) {
front[qn] = -1;
rear[qn] = -1;
} else {
front[qn] = baseIndex + (front[qn] + 1 - baseIndex) % (n / k);
}
return x;
}
}
class GfG { static void Main(string[] args) { int n = 10, k = 3; kQueues queues = new kQueues(n, k);
Console.Write(queues.enqueue(10, 0) + " ");
Console.Write(queues.enqueue(20, 1) + " ");
Console.Write(queues.enqueue(30, 0) + " ");
Console.Write(queues.enqueue(40, 2) + " ");
Console.Write(queues.dequeue(0) + " ");
Console.Write(queues.dequeue(1) + " ");
Console.Write(queues.dequeue(2) + " ");
Console.Write(queues.dequeue(0) + " ");
Console.Write(queues.dequeue(0) + " ");
}
}
JavaScript
// JavaScript program to implement k queues // in a single array (Naive Approach)
class kQueues { constructor(n, k) { this.n = n; this.k = k; this.arr = new Array(n); this.front = new Array(k).fill(-1); this.rear = new Array(k).fill(-1); }
// Function to check if queue 'qn' is empty
isEmpty(qn) {
return this.front[qn] === -1;
}
// Function to check if queue 'qn' is full
isFull(qn) {
let nextPos =
(this.rear[qn] + 1) % (this.n / this.k);
return (nextPos === this.front[qn] %
(this.n / this.k) && this.front[qn] !== -1);
}
// Function to enqueue 'x' into queue 'qn'
enqueue(x, qn) {
if (this.isFull(qn))
return false;
let base = qn * (this.n / this.k);
if (this.isEmpty(qn))
this.front[qn] = base;
this.rear[qn] = (this.rear[qn] === -1) ?
base :
base + (this.rear[qn] + 1 - base) % (this.n / this.k);
this.arr[this.rear[qn]] = x;
return true;
}
// Function to dequeue from queue 'qn'
dequeue(qn) {
if (this.isEmpty(qn))
return -1;
let base = qn * (this.n / this.k);
let x = this.arr[this.front[qn]];
if (this.front[qn] === this.rear[qn]) {
this.front[qn] = -1;
this.rear[qn] = -1;
} else {
this.front[qn] = base +
(this.front[qn] + 1 - base) % (this.n / this.k);
}
return x;
}
}
let n = 10, k = 3; let queues = new kQueues(n, k);
console.log( queues.enqueue(10, 0), queues.enqueue(20, 1), queues.enqueue(30, 0), queues.enqueue(40, 2), queues.dequeue(0), queues.dequeue(1), queues.dequeue(2), queues.dequeue(0), queues.dequeue(0) );
`
Output
1 1 1 1 10 20 40 30 -1
Expected Approach - Using Space Optimized Method
The idea is similar to the stack post. We use a single array for storing elements of all queues along with auxiliary arrays that maintain pointers to the front and rear elements of each queue, as well as tracking the next element in the queue. Instead of dividing the array into fixed segments, we implement a free list structure that keeps track of available spaces in the array. This allows dynamic allocation of array slots to any queue that needs them, making efficient use of the entire array regardless of individual queue sizes.
Following are the extra arrays used:
- **front[]: This is of size k and stores indexes of front elements in all queues. front[i] = -1 indicates an empty queue.
- **rear[]: This is of size k and stores indexes of rear elements in all queues. rear[i] = -1 indicates an empty queue.
- **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.
**Algorithm:
- Initialize arrays
front
andrear
of size k to keep track of the front and rear elements of each queue. Set front[i] = rear[i] = -1 for all 0 ≤ i < k to indicate empty queues. - Initialize an array
next
of size n to link elements in the same queue and maintain a free list. Set next[i] = i+1 for all 0 ≤ i < n-1, and next[n-1] = -1. - Initialize a variable
freeIndex = 0
to point to the first available position in the free list. - To enqueue an element into the qn-th queue:
- Check if the array is full by checking if
freeIndex
is -1. If it is, return false. - Store the current
freeIndex
, updatefreeIndex = next[freeIndex]
to point to the next available slot. - If the queue is empty, update both front and rear of the queue to the allocated index.
- If the queue is not empty, link the new element to the rear by setting
next[rear[qn]] = i
and update rear. - Mark the end of the queue by setting
next[i] = -1
.
- Check if the array is full by checking if
- To dequeue an element from the qn-th queue:
- Check if the queue is empty by checking if
front[qn]
is -1. If it is, return -1. - Get the index of the front element:
i = front[qn]
. - Update the front to the next element in the queue:
front[qn] = next[i]
. - If the queue becomes empty after dequeuing, reset both front and rear to -1.
- Return the position to the free list by setting
next[i] = freeIndex
andfreeIndex = i
. - Return the element value. C++ `
- Check if the queue is empty by checking if
// C++ program to implement k queues // in a single array (Efficient Approach) #include <bits/stdc++.h> using namespace std;
class kQueues {
private:
vector arr;
int n, k;
vector front;
vector rear;
vector next;
int freeIndex;
public: kQueues(int n, int k) { this->n = n; this->k = k; arr.resize(n); front.resize(k, -1); rear.resize(k, -1); next.resize(n);
// Initialize all spaces as free
freeIndex = 0;
for (int i = 0; i < n-1; i++)
next[i] = i + 1;
// -1 is used to indicate end of free list
next[n-1] = -1;
}
// Function to check if queue 'qn' is empty
bool isEmpty(int qn) {
return (front[qn] == -1);
}
// Function to check if array is full
bool isFull() {
return (freeIndex == -1);
}
// Function to enqueue 'x' into queue 'qn'
bool enqueue(int x, int qn) {
// Check if array is full
if (isFull())
return false;
// Get next free index
int i = freeIndex;
freeIndex = next[i];
// If queue is empty, update
// both front and rear
if (isEmpty(qn))
front[qn] = i;
else {
// Link new element to the previous rear
next[rear[qn]] = i;
}
// Update rear
rear[qn] = i;
// Store the element
arr[i] = x;
// Mark end of queue
next[i] = -1;
return true;
}
// Function to dequeue from queue 'qn'
int dequeue(int qn) {
// Check if queue is empty
if (isEmpty(qn))
return -1;
// Get the front index of queue
int i = front[qn];
// Update front
front[qn] = next[i];
// If queue becomes empty
if (front[qn] == -1)
rear[qn] = -1;
// Add the dequeued position to free list
next[i] = freeIndex;
freeIndex = i;
// Return the dequeued element
return arr[i];
}
};
int main() { int n = 10, k = 3; kQueues queues(n, k);
cout << queues.enqueue(10, 0) << " ";
cout << queues.enqueue(20, 1) << " ";
cout << queues.enqueue(30, 0) << " ";
cout << queues.enqueue(40, 2) << " ";
cout << queues.enqueue(50, 1) << " ";
cout << queues.enqueue(60, 0) << " ";
cout << queues.enqueue(70, 2) << " ";
cout << queues.dequeue(0) << " ";
cout << queues.dequeue(1) << " ";
cout << queues.dequeue(2) << " ";
cout << queues.dequeue(0) << " ";
cout << queues.enqueue(80, 0) << " ";
cout << queues.dequeue(0) << " ";
return 0;
}
Java
// Java program to implement k queues
// in a single array (Efficient Approach)
class kQueues {
int[] arr;
int n, k;
int[] front;
int[] rear;
int[] next;
int freeIndex;
kQueues(int n, int k) {
this.n = n;
this.k = k;
arr = new int[n];
front = new int[k];
rear = new int[k];
next = new int[n];
for (int i = 0; i < k; i++)
front[i] = rear[i] = -1;
// Initialize all spaces as free
freeIndex = 0;
for (int i = 0; i < n - 1; i++)
next[i] = i + 1;
// -1 is used to indicate end of free list
next[n - 1] = -1;
}
// Function to check if queue 'qn' is empty
boolean isEmpty(int qn) {
return (front[qn] == -1);
}
// Function to check if array is full
boolean isFull() {
return (freeIndex == -1);
}
// Function to enqueue 'x' into queue 'qn'
boolean enqueue(int x, int qn) {
// Check if array is full
if (isFull())
return false;
// Get next free index
int i = freeIndex;
freeIndex = next[i];
// If queue is empty, update
// both front and rear
if (isEmpty(qn))
front[qn] = i;
else {
// Link new element to the previous rear
next[rear[qn]] = i;
}
// Update rear
rear[qn] = i;
// Store the element
arr[i] = x;
// Mark end of queue
next[i] = -1;
return true;
}
// Function to dequeue from queue 'qn'
int dequeue(int qn) {
// Check if queue is empty
if (isEmpty(qn))
return -1;
// Get the front index of queue
int i = front[qn];
// Update front
front[qn] = next[i];
// If queue becomes empty
if (front[qn] == -1)
rear[qn] = -1;
// Add the dequeued position to free list
next[i] = freeIndex;
freeIndex = i;
// Return the dequeued element
return arr[i];
}
}
class GfG { public static void main(String[] args) { int n = 10, k = 3; kQueues queues = new kQueues(n, k);
System.out.print(queues.enqueue(10, 0) + " ");
System.out.print(queues.enqueue(20, 1) + " ");
System.out.print(queues.enqueue(30, 0) + " ");
System.out.print(queues.enqueue(40, 2) + " ");
System.out.print(queues.enqueue(50, 1) + " ");
System.out.print(queues.enqueue(60, 0) + " ");
System.out.print(queues.enqueue(70, 2) + " ");
System.out.print(queues.dequeue(0) + " ");
System.out.print(queues.dequeue(1) + " ");
System.out.print(queues.dequeue(2) + " ");
System.out.print(queues.dequeue(0) + " ");
System.out.print(queues.enqueue(80, 0) + " ");
System.out.print(queues.dequeue(0) + " ");
}
}
Python
Python program to implement k queues
in a single array (Efficient Approach)
class kQueues: def init(self, n, k): self.n = n self.k = k self.arr = [0] * n self.front = [-1] * k self.rear = [-1] * k self.next = [0] * n
# Initialize all spaces as free
self.freeIndex = 0
for i in range(n - 1):
self.next[i] = i + 1
# -1 is used to indicate end of free list
self.next[n - 1] = -1
# Function to check if queue 'qn' is empty
def isEmpty(self, qn):
return self.front[qn] == -1
# Function to check if array is full
def isFull(self):
return self.freeIndex == -1
# Function to enqueue 'x' into queue 'qn'
def enqueue(self, x, qn):
# Check if array is full
if self.isFull():
return False
# Get next free index
i = self.freeIndex
self.freeIndex = self.next[i]
# If queue is empty, update
# both front and rear
if self.isEmpty(qn):
self.front[qn] = i
else:
# Link new element to the previous rear
self.next[self.rear[qn]] = i
# Update rear
self.rear[qn] = i
# Store the element
self.arr[i] = x
# Mark end of queue
self.next[i] = -1
return True
# Function to dequeue from queue 'qn'
def dequeue(self, qn):
# Check if queue is empty
if self.isEmpty(qn):
return -1
# Get the front index of queue
i = self.front[qn]
# Update front
self.front[qn] = self.next[i]
# If queue becomes empty
if self.front[qn] == -1:
self.rear[qn] = -1
# Add the dequeued position to free list
self.next[i] = self.freeIndex
self.freeIndex = i
# Return the dequeued element
return self.arr[i]
if name == "main": n = 10 k = 3 queues = kQueues(n, k)
print(queues.enqueue(10, 0), end=" ")
print(queues.enqueue(20, 1), end=" ")
print(queues.enqueue(30, 0), end=" ")
print(queues.enqueue(40, 2), end=" ")
print(queues.enqueue(50, 1), end=" ")
print(queues.enqueue(60, 0), end=" ")
print(queues.enqueue(70, 2), end=" ")
print(queues.dequeue(0), end=" ")
print(queues.dequeue(1), end=" ")
print(queues.dequeue(2), end=" ")
print(queues.dequeue(0), end=" ")
print(queues.enqueue(80, 0), end=" ")
print(queues.dequeue(0), end=" ")
C#
// C# program to implement k queues // in a single array (Efficient Approach) using System;
class kQueues { int[] arr; int n, k; int[] front; int[] rear; int[] next; int freeIndex;
public kQueues(int n, int k) {
this.n = n;
this.k = k;
arr = new int[this.n];
front = new int[this.k];
rear = new int[this.k];
next = new int[this.n];
for (int i = 0; i < k; i++)
front[i] = rear[i] = -1;
// Initialize all spaces as free
freeIndex = 0;
for (int i = 0; i < n - 1; i++)
next[i] = i + 1;
// -1 is used to indicate end of free list
next[n - 1] = -1;
}
// Function to check if queue 'qn' is empty
bool isEmpty(int qn) {
return (front[qn] == -1);
}
// Function to check if array is full
bool isFull() {
return (freeIndex == -1);
}
// Function to enqueue 'x' into queue 'qn'
public bool enqueue(int x, int qn) {
// Check if array is full
if (isFull())
return false;
// Get next free index
int i = freeIndex;
freeIndex = next[i];
// If queue is empty, update
// both front and rear
if (isEmpty(qn))
front[qn] = i;
else {
// Link new element to the previous rear
next[rear[qn]] = i;
}
// Update rear
rear[qn] = i;
// Store the element
arr[i] = x;
// Mark end of queue
next[i] = -1;
return true;
}
// Function to dequeue from queue 'qn'
public int dequeue(int qn) {
// Check if queue is empty
if (isEmpty(qn))
return -1;
// Get the front index of queue
int i = front[qn];
// Update front
front[qn] = next[i];
// If queue becomes empty
if (front[qn] == -1)
rear[qn] = -1;
// Add the dequeued position to free list
next[i] = freeIndex;
freeIndex = i;
// Return the dequeued element
return arr[i];
}
}
class GfG { static void Main() { int n = 10, k = 3; kQueues queues = new kQueues(n, k);
Console.Write(queues.enqueue(10, 0) + " ");
Console.Write(queues.enqueue(20, 1) + " ");
Console.Write(queues.enqueue(30, 0) + " ");
Console.Write(queues.enqueue(40, 2) + " ");
Console.Write(queues.enqueue(50, 1) + " ");
Console.Write(queues.enqueue(60, 0) + " ");
Console.Write(queues.enqueue(70, 2) + " ");
Console.Write(queues.dequeue(0) + " ");
Console.Write(queues.dequeue(1) + " ");
Console.Write(queues.dequeue(2) + " ");
Console.Write(queues.dequeue(0) + " ");
Console.Write(queues.enqueue(80, 0) + " ");
Console.Write(queues.dequeue(0) + " ");
}
}
JavaScript
// JavaScript program to implement k queues // in a single array (Efficient Approach)
class kQueues { constructor(n, k) { this.n = n; this.k = k; this.arr = new Array(n); this.front = new Array(k).fill(-1); this.rear = new Array(k).fill(-1); this.next = new Array(n);
// Initialize all spaces as free
this.freeIndex = 0;
for (let i = 0; i < n - 1; i++)
this.next[i] = i + 1;
// -1 is used to indicate end of free list
this.next[n - 1] = -1;
}
// Function to check if queue 'qn' is empty
isEmpty(qn) {
return this.front[qn] === -1;
}
// Function to check if array is full
isFull() {
return this.freeIndex === -1;
}
// Function to enqueue 'x' into queue 'qn'
enqueue(x, qn) {
if (this.isFull())
return false;
let i = this.freeIndex;
this.freeIndex = this.next[i];
if (this.isEmpty(qn))
this.front[qn] = i;
else
this.next[this.rear[qn]] = i;
this.rear[qn] = i;
this.arr[i] = x;
this.next[i] = -1;
return true;
}
// Function to dequeue from queue 'qn'
dequeue(qn) {
if (this.isEmpty(qn))
return -1;
let i = this.front[qn];
this.front[qn] = this.next[i];
if (this.front[qn] === -1)
this.rear[qn] = -1;
this.next[i] = this.freeIndex;
this.freeIndex = i;
return this.arr[i];
}
}
let n = 10, k = 3; let queues = new kQueues(n, k);
console.log( queues.enqueue(10, 0), queues.enqueue(20, 1), queues.enqueue(30, 0), queues.enqueue(40, 2), queues.enqueue(50, 1), queues.enqueue(60, 0), queues.enqueue(70, 2),
queues.dequeue(0),
queues.dequeue(1),
queues.dequeue(2),
queues.dequeue(0),
queues.enqueue(80, 0),
queues.dequeue(0)
);
`
Output
1 1 1 1 1 1 1 10 20 40 30 1 60
The best part of the above implementation is, if there is a slot available in the queue, then an item can be enqueued in any of the queues, i.e., no wastage of space. This method requires some extra space. Space may not be an issue because queue items are typically large, for example, queues of employees, students, etc where every item is of hundreds of bytes. For such large queues, the extra space used is comparatively very less as we use three integer arrays as extra space.
**Issues in efficiently implement k Queues in a single array :
While the circular array implementation of k queues is an efficient way to implement multiple queues in a single array, there are several issues that need to be considered to ensure that the implementation is correct and efficient.
- Size allocation: One issue is deciding how to allocate the size of each queue segment in the array. If the size of one queue segment is too small, that queue may fill up quickly, causing a lot of unnecessary resizing and memory allocation. On the other hand, if the size of one queue segment is too large, there may be a lot of wasted space in the array.
- Overflow/underflow: Another issue is handling overflow and underflow. If the array becomes full, there will be no space to enqueue elements, and if the array becomes empty, there will be no elements left to dequeue. It is important to handle these cases properly to avoid errors or unexpected behavior.
- Tracking size: To properly implement the k queues in a single array, we need to keep track of the size of each queue segment to know how many elements are currently in each queue. This can add overhead to the implementation, as we need to update the size of each segment whenever we enqueue or dequeue an element.
- Implementation complexity: Finally, the circular array implementation of k queues can be more complex to implement and maintain than a simpler implementation using separate arrays for each queue. This is because we need to keep track of multiple pointers and manage the circular nature of the array.
**Examples of Queues in a single array :
- Multi-Threaded Programming: In multi-threaded programming, where multiple threads need to access shared resources in a concurrent manner, a circular array implementation of k queues can be used to implement a thread-safe data structure. Each thread can access a particular queue, and the queues can be managed in a thread-safe manner.
- Resource Management: In a resource management system, such as a job scheduler or task manager, queues can be used to manage resources efficiently. Using a single array to implement multiple queues allows efficient management of multiple resources.
- Web Servers: In web servers, queues can be used to manage incoming requests from clients. A single array implementation of multiple queues can be used to manage multiple request queues, such as HTTP and FTP requests, in a single data structure.
- Operating Systems: In operating systems, queues can be used to manage system resources such as CPU time and memory. A circular array implementation of multiple queues can be used to manage multiple queues of processes or threads, allowing efficient resource management.
- Data Structures: Queues are a fundamental data structure used in many algorithms and software applications. A circular array implementation of multiple queues can be used to implement queue-based algorithms such as breadth-first search, shortest path algorithms, and simulation algorithms.