Open In App

implement k Queues in a single array

Last Updated : 27 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

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)
);

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:

  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.

Algorithm:

  1. 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.
  2. 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.
  3. Initialize a variable freeIndex = 0 to point to the first available position in the free list.
  4. 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.
  5. 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)
);

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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 :

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.


Next Article
Article Tags :
Practice Tags :

Similar Reads