C++ Program to Implement Queue using Array

A queue is a linear data structure that consists of elements arranged in a sequential order where one end is used to add elements, and another for removing them which results in the FIFO (First-In First-Out) order of operations. In this article, we will learn how to write a program to implement queues using an array in C++.

Queue using Array in C++

The queue is a linear data structure that has the following properties:-

  • It works on the principle of FIFO (First In First Out)
  • It has mainly 2 pointers to perform operations: Front & Rear. The Rear is for insertion and the Front is for deletion
  • It is a linear data structure that gives sequential one-way access to the elements. Even though we can implement it using an array, we cannot access any element through indices directly because access to elements is given only through the rear and front pointers.

To understand better about the queue data structure let us go through the following diagram which describes the workflow of the queue implemented using an array:


Explanation:

  1. Initially our array based Queue consists of : [10, 30, 40, 50, 40, 60]
  2. And then we perform an Enqueue and a Dequeue Operation for element 10 and 15 respectively.
  3. After performing operations, our final queue is : [30, 40, 50, 40, 60, 15]

Representation of Queue in C++

We can represent a queue using a class that contains:

  • An array to store the data.
  • Front and back index pointer.
  • Constructor to initialize the queue.
  • Member functions that provide enqueue and dequeue operations.

Basic Operations on Queue in C++

In order to implement a queue using array, we must be aware of the basic operations that are performed in a queue to manipulate the elements present inside it. Following are the basic operations of the queue data structure:

Operation

Description

Time Complexity

Space Complexity

Enqueue

Inserts an element into the queue using the rear pointer.

O(1)

O(1)

Dequeue

Deletes an element from the queue using the front pointer and returns it.

O(1)

O(1)

getFront

Return the element from the queue denoted by the front pointer.

O(1)

O(1)

isEmpty

Returns true if the queue is empty.

O(1)

O(1)

isFull

Returns true if the queue is fully occupied and there is no space left.

O(1)

O(1)

The two main operations related to the queue data structure are enqueue and dequeue. Let us understand about the implementation of both the enqueue and dequeue operations.

Implementation of Enqueue Operation

The enqueue operation of the queue inserts an element into the queue if it is not full through the rear pointer. We need to check if the queue is full before enqueue (queue overflow).

Algorithm of Enqueue

Following is the algorithm for the enqueue operation:

  • Check if the queue is full using the isFull function.
  • If not full, increment the rear pointer and add the new element to the rear position.
  • If the queue was empty before enqueueing, also update the front pointer.

Implementation of Dequeue Operation

The dequeue operation of the queue deletes an element from the queue if it is not empty through the front pointer.

Algorithm of Dequeue

Following is the algorithm for the dequeue operation:

  • Check if the queue is empty using the isEmpty function.
  • If not empty, store the element at the front position.
  • Increment the front pointer to remove the element from the queue.
  • If the queue becomes empty after dequeueing, reset both front and rear pointers to -1.

Implementation of Front Operation

This operation returns the element at the front of the queue. It is the element that will be removed first when we perform dequeue.

Algorithm of Front

Following is the algorithm for the front operation:

  • Check if the queue is empty. If the queue is empty, return -1.
  • If the queue is not empty, return the element pointed by the front pointer.

Implementation of isEmpty Operation

This operation checks whether the given queue has any element or is it empty. This function returns true if the queue is empty, false otherwise. We know that when the queue is empty initially, the front = -1. When we dequeue all the elements, then the front > rear.

Algorithm of isEmpty

Following is the algorithm for the isEmpty operation:

  • If front == -1 OR front > rear is true, then we can say that the queue is empty.
  • It it evaluates as false, then we can say that there are elements in the queue.

Implementation of isFull Operation

The isFull operation checks whenther the queue is full. It means that whether it contains n elements where n is the size of the array using which the queue is implemented.

Algorithm of isFull

Following is the algorithm for the isFull operation:

  • Check if the rear == MAX_ARRAY_SIZE – 1.
  • If it is true, then the queue is full.
  • If its false, then it means that there is space left in the queue.

C++ Program to Implement Queue using Array

The following program demonstrates how we can implement a queue using array in C++:

C++
// C++ Program to implement a queue using array
#include <iostream>
using namespace std;

// defining the max size of the queue
#define MAX_SIZE 100

// Implement the queue data structure
class Queue {
public:
    int front;
    int rear;
    int arr[MAX_SIZE];

    // initializing pointers in the constructor
    Queue(): front(-1), rear(-1) {}

    // Function to check if the queue is empty or not
    bool isEmpty() { return front == -1 || front > rear; }

    // Function to check if the queue is full or not
    bool isFull() { return rear == MAX_SIZE - 1; }

    // Function to get the front element of the queue
    int getFront()
    {
        if (isEmpty()) {
            cout << "Queue is empty" << endl;
            return -1;
        }
        return arr[front];
    }

    // Function to get the rear element of the queue
    int getRear()
    {
        if (isEmpty()) {
            cout << "Queue is empty" << endl;
            return -1;
        }
        return arr[rear];
    }

    // Function to enqueue elements from the queue
    void enqueue(int val)
    {
        // Check overflow condition
        if (isFull()) {
            cout << "Queue is full" << endl;
            return;
        }
        // if queue is empty, set front to 0
        if (isEmpty())
            front = 0;

        rear++;
        arr[rear] = val;
    }

    // Function to dequeue elements from the queue
    int dequeue()
    {
        // Check underflow condition
        if (isEmpty()) {
            cout << "Queue is empty" << endl;
            return -1;
        }
        int ans = arr[front];
        front++;

        // if queue becomes empty, reset both pointers
        if (isEmpty())
            front = rear = -1;

        return ans;
    }

    // Display function to print the queue
    void display()
    {
        if (isEmpty()) {
            cout << "Queue is empty" << endl;
            return;
        }
        cout << "Queue:  ";
        for (int i = front; i <= rear; i++) {
            cout << arr[i] << " ";
        }

        cout << endl;
    }
};

int main()
{
    // Created Queue of size 5
    Queue q;

    // Enqueueing elements
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);

    // Displaying status of the queue after enqueuing
    cout << "\nAfter Enqueueing:" << endl;

    cout << "Front element: " << q.getFront() << endl;
    cout << "Rear element: " << q.getRear() << endl;

    q.display();

    // Enqueueing more elements
    q.enqueue(4);
    q.enqueue(5);

    // Displaying the updated queue
    q.display();

    // Enqueueing one more element to demonstrate overflow
    // condition
    q.enqueue(6);

    // Dequeueing elements
    cout << "\nDequeueing elements:" << endl;
    cout << "Dequeued element: " << q.dequeue() << endl;
    cout << "Dequeued element: " << q.dequeue() << endl;

    // Displaying status of the queue after dequeueing
    cout << "\nAfter Dequeueing:" << endl;

    cout << "Front element: " << q.getFront() << endl;
    cout << "Rear element: " << q.getRear() << endl;

    q.display();

    return 0;
}


Output

After Enqueueing:
Front element: 1
Rear element: 3
Queue: 1 2 3
Queue: 1 2 3 4 5

Dequeueing elements:
Dequeued element: 1
Dequeued element: 2

After Dequeueing:
Front element: 3
Rear element: 6
Queue: 3 4 5 6

Problem with this Implementation

Consider the situation where we insert the elements in the queue till it is full. After that, we removed all the elements. Now, the front will point to the element one more than the rear and will be equal to the MAX_SIZE which is the condition for the Full queue. Now even though the queue is empty, it still will show queue overflow.

To resoolve this, we use the concept of the circular queue where we perform the circular or modular increment.

Refer to this aritcle for more information.

Applications of Queue

Due to its FIFO nature, queue is a widely utilised data structure in a variety of real world applications :-

  1. Computer Science Fundamentals: its utilised in mostly the core operating system concepts like Job Scheduling Algorithms, Memory management for processing, basically putting the processes inside a queue so that they can be executed concurrently by the processor
  2. Algorithms: To store addresses of tree nodes, linked list nodes, and Graph Nodes BFS (Breadth First Search) etc.
  3. Real World Application: In a music or video player app you must’ve seen the option “Add to Queue” which is basically the Enqueue operation!

Conclusion

In this article we’ve covered the most important aspects of Queue data structure like working, basic operations, implementation using array in C++, applications etc. We have also seen that the queue provide O(1) time and space complexity for all operation. Though the operations provide limited capablity.