We have discussed efficient implementation of k stack in an array. In this post, same for queue is discussed. Following is the detailed problem statement.

Create a data structure kQueues that represents k queues. Implementation of kQueues should use only one array, i.e., k queues should use the same array for storing elements. Following functions must be supported by kQueues.

*enqueue(int x, int qn) –> adds x to queue number ‘qn’ where qn is from 0 to k-1
dequeue(int qn) –> deletes an element from queue number ‘qn’ where qn is from 0 to k-1
*

**Method 1 (Divide the array in slots of size n/k)**

A simple way to implement k queues is to divide the array in k slots of size n/k each, and fix the slots for different queues, i.e., use arr[0] to arr[n/k-1] for first queue, and arr[n/k] to arr[2n/k-1] for queue2 where arr[] is the array to be used to implement two queues and size of array be n.

The problem with this method is inefficient use of array space. An enqueue operation may result in overflow even if there is space available in arr[]. For example, consider k as 2 and array size n as 6. Let we enqueue 3 elements to first and do not enqueue anything to second second queue. When we enqueue 4th element to first queue, there will be overflow even if we have space for 3 more elements in array.

**Method 2 (A space efficient implementation)**

The idea is similar to the stack post, here we need to use three extra arrays. In stack post, we needed two extra arrays, one more array is required because in queues, enqueue() and dequeue() operations are done at different ends.

Following are the three extra arrays are used:

1) **front[]**: This is of size k and stores indexes of front elements in all queues.

2) **rear[]**: This is of size k and stores indexes of rear elements in all queues.

2) **next[]**: This is of size n and stores indexes of next item for all items in array arr[].

Here arr[] is actual array that stores k stacks.

Together with k queues, a stack of free slots in arr[] is also maintained. The top of this stack is stored in a variable ‘free’.

All entries in front[] are initialized as -1 to indicate that all queues are empty. All entries next[i] are initialized as i+1 because all slots are free initially and pointing to next slot. Top of free stack, ‘free’ is initialized as 0.

Following is C++ implementation of the above idea.

`// A C++ program to demonstrate implementation of k queues in a single ` `// array in time and space efficient way ` `#include<iostream> ` `#include<climits> ` `using` `namespace` `std; ` ` ` `// A C++ class to represent k queues in a single array of size n ` `class` `kQueues ` `{ ` ` ` `int` `*arr; ` `// Array of size n to store actual content to be stored in queue ` ` ` `int` `*front; ` `// Array of size k to store indexes of front elements of queue ` ` ` `int` `*rear; ` `// Array of size k to store indexes of rear elements of queue ` ` ` `int` `*next; ` `// Array of size n to store next entry in all queues ` ` ` `// and free list ` ` ` `int` `n, k; ` ` ` `int` `free` `; ` `// To store beginning index of free list ` `public` `: ` ` ` `//constructor to create k queue in an array of size n ` ` ` `kQueues(` `int` `k, ` `int` `n); ` ` ` ` ` `// A utility function to check if there is space available ` ` ` `bool` `isFull() { ` `return` `(` `free` `== -1); } ` ` ` ` ` `// To enqueue an item in queue number 'qn' where qn is from 0 to k-1 ` ` ` `void` `enqueue(` `int` `item, ` `int` `qn); ` ` ` ` ` `// To dequeue an from queue number 'qn' where qn is from 0 to k-1 ` ` ` `int` `dequeue(` `int` `qn); ` ` ` ` ` `// To check whether queue number 'qn' is empty or not ` ` ` `bool` `isEmpty(` `int` `qn) { ` `return` `(front[qn] == -1); } ` `}; ` ` ` `// Constructor to create k queues in an array of size n ` `kQueues::kQueues(` `int` `k1, ` `int` `n1) ` `{ ` ` ` `// Initialize n and k, and allocate memory for all arrays ` ` ` `k = k1, n = n1; ` ` ` `arr = ` `new` `int` `[n]; ` ` ` `front = ` `new` `int` `[k]; ` ` ` `rear = ` `new` `int` `[k]; ` ` ` `next = ` `new` `int` `[n]; ` ` ` ` ` `// Initialize all queues as empty ` ` ` `for` `(` `int` `i = 0; i < k; i++) ` ` ` `front[i] = -1; ` ` ` ` ` `// Initialize all spaces as free ` ` ` `free` `= 0; ` ` ` `for` `(` `int` `i=0; i<n-1; i++) ` ` ` `next[i] = i+1; ` ` ` `next[n-1] = -1; ` `// -1 is used to indicate end of free list ` `} ` ` ` `// To enqueue an item in queue number 'qn' where qn is from 0 to k-1 ` `void` `kQueues::enqueue(` `int` `item, ` `int` `qn) ` `{ ` ` ` `// Overflow check ` ` ` `if` `(isFull()) ` ` ` `{ ` ` ` `cout << ` `"\nQueue Overflow\n"` `; ` ` ` `return` `; ` ` ` `} ` ` ` ` ` `int` `i = ` `free` `; ` `// Store index of first free slot ` ` ` ` ` `// Update index of free slot to index of next slot in free list ` ` ` `free` `= next[i]; ` ` ` ` ` `if` `(isEmpty(qn)) ` ` ` `front[qn] = i; ` ` ` `else` ` ` `next[rear[qn]] = i; ` ` ` ` ` `next[i] = -1; ` ` ` ` ` `// Update next of rear and then rear for queue number 'qn' ` ` ` `rear[qn] = i; ` ` ` ` ` `// Put the item in array ` ` ` `arr[i] = item; ` `} ` ` ` `// To dequeue an from queue number 'qn' where qn is from 0 to k-1 ` `int` `kQueues::dequeue(` `int` `qn) ` `{ ` ` ` `// Underflow checkSAS ` ` ` `if` `(isEmpty(qn)) ` ` ` `{ ` ` ` `cout << ` `"\nQueue Underflow\n"` `; ` ` ` `return` `INT_MAX; ` ` ` `} ` ` ` ` ` `// Find index of front item in queue number 'qn' ` ` ` `int` `i = front[qn]; ` ` ` ` ` `front[qn] = next[i]; ` `// Change top to store next of previous top ` ` ` ` ` `// Attach the previous front to the beginning of free list ` ` ` `next[i] = ` `free` `; ` ` ` `free` `= i; ` ` ` ` ` `// Return the previous front item ` ` ` `return` `arr[i]; ` `} ` ` ` `/* Driver program to test kStacks class */` `int` `main() ` `{ ` ` ` `// Let us create 3 queue in an array of size 10 ` ` ` `int` `k = 3, n = 10; ` ` ` `kQueues ks(k, n); ` ` ` ` ` `// Let us put some items in queue number 2 ` ` ` `ks.enqueue(15, 2); ` ` ` `ks.enqueue(45, 2); ` ` ` ` ` `// Let us put some items in queue number 1 ` ` ` `ks.enqueue(17, 1); ` ` ` `ks.enqueue(49, 1); ` ` ` `ks.enqueue(39, 1); ` ` ` ` ` `// Let us put some items in queue number 0 ` ` ` `ks.enqueue(11, 0); ` ` ` `ks.enqueue(9, 0); ` ` ` `ks.enqueue(7, 0); ` ` ` ` ` `cout << ` `"Dequeued element from queue 2 is "` `<< ks.dequeue(2) << endl; ` ` ` `cout << ` `"Dequeued element from queue 1 is "` `<< ks.dequeue(1) << endl; ` ` ` `cout << ` `"Dequeued element from queue 0 is "` `<< ks.dequeue(0) << endl; ` ` ` ` ` `return` `0; ` `} ` |

Output:

Dequeued element from queue 2 is 15 Dequeued element from queue 1 is 17 Dequeued element from queue 0 is 11

Time complexities of enqueue() and dequeue() is O(1).

The best part of above implementation is, if there is a slot available in 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.

This article is contributed by **Sachin**. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above