Queue Data Structure in C++ with Real-Time Examples

Introduction to Queue

A Queue is a linear data structure that follows the principle:

  • FIFO – First In, First Out

This means:

  • The element inserted first is removed first.

  • Just like a real-life queue of people waiting for service.

Queues are widely used in:

  • CPU scheduling

  • Printer spooling

  • Call center systems

  • Order processing systems

  • Networking packet management

Objective of This Lab

This lab introduces:

  • How to access the front and rear pointers

  • How to enqueue (insert) data

  • How to dequeue (delete) data

By the end of this session, you will understand both theory and implementation in C++.

Real-Time Example

🏦 Example: Bank Service Counter

Imagine customers standing in a line:

  • The first customer who enters the line gets served first.

  • New customers join at the rear.

  • Service happens from the front.

This is exactly how a queue works in programming.

The main operations are:

Enqueue βˆ’ place an element at the tail of the queue;
Dequeue βˆ’ take out an element form the front of the queue;
Delete βˆ’ delete the whole queue

Queue Implementation Using Array in C++

We will implement Queue using:

  • Array

  • Front pointer

  • Rear pointer

  • Class-based structure (OOP approach)

πŸ’» Complete C++ Implementation

#include <iostream>
using namespace std;

#define SIZE 5

class Queue {
    private:
    int arr[SIZE];
    int front;
    int rear;

    public:
    // Constructor
    Queue() {
        front = -1;
        rear = -1;
    }

    // Check if queue is empty
    bool isEmpty() {
        return (front == -1 || front > rear);
    }

    // Check if queue is full
    bool isFull() {
        return (rear == SIZE - 1);
    }

    // Enqueue operation
    void enqueue(int value) {
        if (isFull()) {
            cout << "Queue Overflow! Cannot insert " << value << endl;
            return;
        }

        if (front == -1)
            front = 0;

        arr[++rear] = value;
        cout << value << " inserted into queue." << endl;
    }

    // Dequeue operation
    void dequeue() {
        if (isEmpty()) {
            cout << "Queue Underflow! Queue is empty." << endl;
            return;
        }

        cout << arr[front++] << " removed from queue." << endl;
    }

    // Display queue elements
    void display() {
        if (isEmpty()) {
            cout << "Queue is empty." << endl;
            return;
        }

        cout << "Queue elements: ";
        for (int i = front; i <= rear; i++) {
            cout << arr[i] << " ";
        }
        cout << endl;
    }

    // Access front element
    void getFront() {
        if (!isEmpty())
            cout << "Front element: " << arr[front] << endl;
    }

    // Access rear element
    void getRear() {
        if (!isEmpty())
            cout << "Rear element: " << arr[rear] << endl;
    }
};

int main() {
    Queue q;

    q.enqueue(10);
    q.enqueue(20);
    q.enqueue(30);

    q.display();

    q.getFront();
    q.getRear();

    q.dequeue();
    q.display();

    return 0;
}

Activity 1:

Implement an array-based FIFO Queue

#include <iostream>
using namespace std;

class Queue   // Renamed properly to Queue
{
    private:
    int size;      // capacity
    int *q;        // dynamic array
    int front;     // front index
    int rear;      // rear index

    public:
    // Default constructor
    Queue()
    {
        size = 10;
        q = new int[size];
        front = -1;
        rear = -1;
    }

    // Overloaded constructor
    Queue(int x)
    {
        size = x;
        q = new int[size];
        front = -1;
        rear = -1;
    }

    // Destructor to free memory
    ~Queue()
{
    delete[] q;
}

    // Check if queue is empty
    bool is_empty()
    {
        return (front == -1);
    }

    // Check if queue is full
    bool is_full()
    {
        return (rear == size - 1);
    }

    // Display queue elements
    void display()
    {
        if (is_empty())
        {
            cout << "\nQueue is empty.";
        }
        else
        {
            for (int i = front; i <= rear; i++)
            {
                cout << "\nValue at index " << i << " is: " << q[i];
            }
        }
    }

    // Enqueue operation
    void enqueue(int x)
    {
        if (is_full())
        {
            cout << "\nNo space. Queue is full.";
        }
        else
        {
            if (is_empty())
            {
                front = rear = 0;
            }
            else
            {
                rear++;
            }
            q[rear] = x;
        }
    }

    // Dequeue operation
    int dequeue()
    {
        if (is_empty())
        {
            cout << "\nQueue is already empty.";
            return -1;
        }
        else
        {
            int x = q[front];

            if (front == rear)
            {
                front = rear = -1;
            }
            else
            {
                front++;
            }

            return x;
        }
    }
};

int main()
{
    Queue q1;      // Default constructor (size 10)
    Queue q2(5);   // Size 5
    Queue q3(15);  // Size 15

    q1.enqueue(5);
    q2.enqueue(7);
    q3.enqueue(6);

    int x = q2.dequeue();
    cout << "\nDequeued element from q2 is: " << x;

    return 0;
}

Activity 3:

Consider the activity-1 where there was an issue of space and to resolve this we applied the shifting. The problem with shifting is that it increases the complexity. The solution of this is circular queue. Circular Queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and the last position is connected back to the first position to make a circle. We apply the formula (Rear=(Rear+1) mod Queue Size) to move the rear to next index.

Implement an Array based circular Queue that is generic in nature (use template classes), apply proper checks of Queue Full and Queue Empty before Enque and DeQue operations.

 

Below is the complete implementation of a Generic (Template-Based) Circular Queue using Array in C++.

This implementation:

  • Uses template class (generic in nature)

  • Applies FIFO principle

  • Uses circular logic:

    rear = (rear + 1) % size
  • Properly checks:

    • Queue Full

    • Queue Empty

  • Avoids shifting (efficient O(1) operations)

#include <iostream>
using namespace std;

template <class T>
class CircularQueue {
    private:
    T* arr;          // Dynamic array
    int front;
    int rear;
    int capacity;
    int count;       // Number of elements in queue

    public:
    // Constructor
    CircularQueue(int size) {
        capacity = size;
        arr = new T[capacity];
        front = 0;
        rear = -1;
        count = 0;
    }

    // Destructor
    ~CircularQueue() {
        delete[] arr;
    }

    // Check if queue is empty
    bool isEmpty() {
        return (count == 0);
    }

    // Check if queue is full
    bool isFull() {
        return (count == capacity);
    }

    // Enqueue operation
    void enqueue(T value) {
        if (isFull()) {
            cout << "Queue Overflow! Cannot insert element.\n";
            return;
        }

        rear = (rear + 1) % capacity;  // Circular increment
        arr[rear] = value;
        count++;

        cout << value << " inserted into circular queue.\n";
    }

    // Dequeue operation
    T dequeue() {
        if (isEmpty()) {
            cout << "Queue Underflow! Queue is empty.\n";
            return T();   // Return default value
        }

        T value = arr[front];
        front = (front + 1) % capacity;  // Circular increment
        count--;

        return value;
    }

    // Get front element
    T getFront() {
        if (isEmpty()) {
            cout << "Queue is empty.\n";
            return T();
        }
        return arr[front];
    }

    // Get rear element
    T getRear() {
        if (isEmpty()) {
            cout << "Queue is empty.\n";
            return T();
        }
        return arr[rear];
    }

    // Display queue elements
    void display() {
        if (isEmpty()) {
            cout << "Queue is empty.\n";
            return;
        }

        cout << "Circular Queue elements: ";
        for (int i = 0; i < count; i++) {
            cout << arr[(front + i) % capacity] << " ";
        }
        cout << endl;
    }
};

int main() {
    CircularQueue<int> q(5);

    q.enqueue(10);
    q.enqueue(20);
    q.enqueue(30);
    q.enqueue(40);
    q.enqueue(50);

    q.display();

    cout << "Dequeued element: " << q.dequeue() << endl;
    cout << "Dequeued element: " << q.dequeue() << endl;

    q.display();

    q.enqueue(60);
    q.enqueue(70);

    q.display();

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

    return 0;
}

 

3) Graded Lab Tasks

Lab Task 1

Implement the methods developed in Activity 1 for Dynmaic Queue i.e. Linked Implementation of the Queue.

Lab Task 2

Implement the Deque in a linked list.

πŸ” Understanding Front and Rear Pointers

Pointer Purpose
Front Points to first element
Rear Points to last element

When:

  • front > rear β†’ Queue becomes empty.

  • rear == SIZE - 1 β†’ Queue becomes full.

 

⏱️ Time Complexity

Operation Complexity
Enqueue O(1)
Dequeue O(1)
Access O(1)
Display O(n)

 

Advantages of Queue

  • Simple structure

  • Efficient insertion and deletion

  • Useful in scheduling and buffering systems

Limitations

  • Fixed size in array implementation

  • Wasted memory after multiple dequeues (in simple queue)

  • Circular queue solves this limitation

 

FAQ Section

What is FIFO in Queue?

FIFO stands for First In First Out, meaning the first inserted element is removed first.

What is the difference between Stack and Queue?

Stack follows LIFO, while Queue follows FIFO.

What are real-world uses of Queue?

CPU scheduling, order processing, call management systems.

πŸŽ“ Conclusion

The Queue Data Structure is fundamental in computer science. Understanding:

  • Front and rear pointers

  • Enqueue operation

  • Dequeue operation

builds a strong foundation for advanced data structures like circular queue, priority queue, and deque.

Mastering queue implementation in C++ prepares students for:

  • Lab exams

  • Coding interviews

  • Competitive programming

Write A Comment