implement k Queues in a single array
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<int> arr;
int n, k;
vector<int> front;
vector<int> 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)
);
Output1 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
and rear
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
, update freeIndex = 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
.
- 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
and freeIndex = i
. - Return the element value.
C++
// C++ program to implement k queues
// in a single array (Efficient Approach)
#include <bits/stdc++.h>
using namespace std;
class kQueues {
private:
vector<int> arr;
int n, k;
vector<int> front;
vector<int> rear;
vector<int> 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)
);
Output1 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.
Similar Reads
Queue Data Structure
A Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Introduction to Queue Data Structure
Queue is a linear data structure that follows FIFO (First In First Out) Principle, so the first element inserted is the first to be popped out. FIFO Principle in Queue: FIFO Principle states that the first element added to the Queue will be the first one to be removed or processed. So, Queue is like
5 min read
Introduction and Array Implementation of Queue
Similar to Stack, Queue is a linear data structure that follows a particular order in which the operations are performed for storing data. The order is First In First Out (FIFO). One can imagine a queue as a line of people waiting to receive something in sequential order which starts from the beginn
2 min read
Queue - Linked List Implementation
In this article, the Linked List implementation of the queue data structure is discussed and implemented. Print '-1' if the queue is empty. Approach: To solve the problem follow the below idea: we maintain two pointers, front and rear. The front points to the first item of the queue and rear points
8 min read
Applications, Advantages and Disadvantages of Queue
A Queue is a linear data structure. This data structure follows a particular order in which the operations are performed. The order is First In First Out (FIFO). It means that the element that is inserted first in the queue will come out first and the element that is inserted last will come out last
5 min read
Different Types of Queues and its Applications
Introduction : A Queue is a linear structure that follows a particular order in which the operations are performed. The order is First In First Out (FIFO). A good example of a queue is any queue of consumers for a resource where the consumer that came first is served first. In this article, the diff
8 min read
Queue implementation in different languages
Queue in C++ STL
In C++, queue container follows the FIFO (First In First Out) order of insertion and deletion. According to it, the elements that are inserted first should be removed first. This is possible by inserting elements at one end (called back) and deleting them from the other end (called front) of the dat
5 min read
Queue Interface In Java
The Queue Interface is a part of java.util package and extends the Collection interface. It stores and processes the data in order means elements are inserted at the end and removed from the front. Key Features: Most implementations, like PriorityQueue, do not allow null elements.Implementation Clas
12 min read
Queue in Python
Like a stack, the queue is a linear data structure that stores items in a First In First Out (FIFO) manner. With a queue, the least recently added item is removed first. A good example of a queue is any queue of consumers for a resource where the consumer that came first is served first. Operations
6 min read
C# Queue with Examples
A Queue in C# is a collection that follows the First-In-First-Out (FIFO) principle which means elements are processed in the same order they are added. It is a part of the System.Collections namespace for non-generic queues and System.Collections.Generic namespace for generic queues. Key Features: F
6 min read
Implementation of Queue in Javascript
A Queue is a linear data structure that follows the FIFO (First In, First Out) principle. Elements are inserted at the rear and removed from the front. Queue Operationsenqueue(item) - Adds an element to the end of the queue.dequeue() - Removes and returns the first element from the queue.peek() - Re
7 min read
Queue in Go Language
A queue is a linear structure that follows a particular order in which the operations are performed. The order is First In First Out (FIFO). Now if you are familiar with other programming languages like C++, Java, and Python then there are inbuilt queue libraries that can be used for the implementat
4 min read
Queue in Scala
A queue is a first-in, first-out (FIFO) data structure. Scala offers both an immutable queue and a mutable queue. A mutable queue can be updated or extended in place. It means one can change, add, or remove elements of a queue as a side effect. Immutable queue, by contrast, never change. In Scala, Q
3 min read
Some question related to Queue implementation
Easy problems on Queue
Detect cycle in an undirected graph using BFS
Given an undirected graph, the task is to determine if cycle is present in it or not. Examples: Input: V = 5, edges[][] = [[0, 1], [0, 2], [0, 3], [1, 2], [3, 4]] Output: trueExplanation: The diagram clearly shows a cycle 0 â 2 â 1 â 0. Input: V = 4, edges[][] = [[0, 1], [1, 2], [2, 3]] Output: fals
6 min read
Breadth First Search or BFS for a Graph
Given a undirected graph represented by an adjacency list adj, where each adj[i] represents the list of vertices connected to vertex i. Perform a Breadth First Search (BFS) traversal starting from vertex 0, visiting vertices from left to right according to the adjacency list, and return a list conta
15+ min read
Traversing directory in Java using BFS
Given a directory, print all files and folders present in directory tree rooted with given directory. We can iteratively traverse directory in BFS using below steps. We create an empty queue and we first enqueue given directory path. We run a loop while queue is not empty. We dequeue an item from qu
2 min read
Vertical Traversal of a Binary Tree
Given a Binary Tree, the task is to find its vertical traversal starting from the leftmost level to the rightmost level. If multiple nodes pass through a vertical line, they should be printed as they appear in the level order traversal of the tree. Examples: Input: Output: [[4], [2], [1, 5, 6], [3,
10 min read
Print Right View of a Binary Tree
Given a Binary Tree, the task is to print the Right view of it. The right view of a Binary Tree is a set of rightmost nodes for every level. Examples: Example 1: The Green colored nodes (1, 3, 5) represents the Right view in the below Binary tree. Example 2: The Green colored nodes (1, 3, 4, 5) repr
15+ min read
Find Minimum Depth of a Binary Tree
Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. For example, minimum depth of below Binary Tree is 2. Note that the path must end on a leaf node. For example, the minimum depth of below Bi
15 min read
Check whether a given graph is Bipartite or not
Given a graph with V vertices numbered from 0 to V-1 and a list of edges, determine whether the graph is bipartite or not. Note: A bipartite graph is a type of graph where the set of vertices can be divided into two disjoint sets, say U and V, such that every edge connects a vertex in U to a vertex
9 min read
Intermediate problems on Queue
Flatten a multilevel linked list using level order traversal
Given a linked list where in addition to the next pointer, each node has a child pointer, which may or may not point to a separate list. These child lists may have one or more children of their own to produce a multilevel linked list. Given the head of the first level of the list. The task is to fla
9 min read
Level with maximum number of nodes
Given a binary tree, the task is to find the level in a binary tree that has the maximum number of nodes. Note: The root is at level 0. Examples: Input: Binary Tree Output : 2Explanation: Input: Binary tree Output:1Explanation Using Breadth First Search - O(n) time and O(n) spaceThe idea is to trave
12 min read
Find if there is a path between two vertices in a directed graph
Given a Directed Graph and two vertices in it, check whether there is a path from the first given vertex to second. Example: Consider the following Graph: Input : (u, v) = (1, 3) Output: Yes Explanation: There is a path from 1 to 3, 1 -> 2 -> 3 Input : (u, v) = (3, 6) Output: No Explanation: T
15 min read
Print all nodes between two given levels in Binary Tree
Given a binary tree, print all nodes between two given levels in a binary tree. Print the nodes level-wise, i.e., the nodes for any level should be printed from left to right. In the above tree, if the starting level is 2 and the ending level is 3 then the solution should print: 2 3 4 5 6 7 Note: Le
15 min read
Find next right node of a given key
Given a Binary tree and a key in the binary tree, find the node right to the given key. If there is no node on right side, then return NULL. Expected time complexity is O(n) where n is the number of nodes in the given binary tree. For example, consider the following Binary Tree. Output for 2 is 6, o
15+ min read
Minimum steps to reach target by a Knight | Set 1
Given a square chessboard of n x n size, the position of the Knight and the position of a target are given. We need to find out the minimum steps a Knight will take to reach the target position. Examples: Input: knightPosition: (1, 3) , targetPosition: (5, 0) Output: 3Explanation: In above diagram K
9 min read
Islands in a graph using BFS
Given an n x m grid of 'W' (Water) and 'L' (Land), the task is to count the number of islands. An island is a group of adjacent 'L' cells connected horizontally, vertically, or diagonally, and it is surrounded by water or the grid boundary. The goal is to determine how many distinct islands exist in
15+ min read
Level order traversal line by line (Using One Queue)
Given a Binary Tree, the task is to print the nodes level-wise, each level on a new line. Example: Input: Output:12 34 5 Table of Content [Expected Approach â 1] Using Queue with delimiter â O(n) Time and O(n) Space[Expected Approach â 2] Using Queue without delimiter â O(n) Time and O(n) Space[Expe
12 min read
First non-repeating character in a stream
Given an input stream s consisting solely of lowercase letters, you are required to identify which character has appeared only once in the stream up to each point. If there are multiple characters that have appeared only once, return the one that first appeared. If no character has appeared only onc
15+ min read