#include <iostream>
using namespace std;
class LinearQueue {
private:
int front, rear;
int Q[5]; // Size limited to 5
public:
LinearQueue() {
front = -1;
rear = -1;
cout << "Initial state => Front: " << front << ", Rear: " << rear << endl;
bool isFull() {
return rear == 4; // Max index for size 5 is 4
bool isEmpty() {
return front == -1 || front > rear;
void enqueue(int value) {
if (isFull()) {
cout << " Queue Overflow! Cannot insert " << value << endl;
displayPointers();
return;
}
if (isEmpty()) {
front = 0;
rear++;
Q[rear] = value;
cout << " Inserted: " << value << endl;
displayPointers();
void dequeue() {
if (isEmpty()) {
cout << " Queue Underflow! Nothing to delete.\n";
displayPointers();
return;
int deletedValue = Q[front];
front++;
cout << " Deleted: " << deletedValue << endl;
if (front > rear) {
// Queue becomes empty again
front = rear = -1;
displayPointers();
}
void display() {
if (isEmpty()) {
cout << "Queue is empty.\n";
return;
cout << "Queue elements: ";
for (int i = front; i <= rear; i++) {
cout << Q[i] << " ";
cout << endl;
void displayPointers() {
cout << "Front: " << front << ", Rear: " << rear << endl;
};
int main() {
LinearQueue q;
int choice, value;
do {
cout << "\n====== MENU ======\n";
cout << "1. Insert (enqueue)\n2. Delete (dequeue)\n3. Display Queue\n4. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter value to insert: ";
cin >> value;
q.enqueue(value);
break;
case 2:
q.dequeue();
break;
case 3:
q.display();
break;
case 4:
cout << "Exiting program.\n";
break;
default:
cout << "Invalid choice. Try again.\n";
} while (choice != 4);
return 0;
}
#include <iostream>
using namespace std;
class CircularQueue {
private:
int front, rear;
int Q[5]; // Max size is 5
const int SIZE = 5;
public:
CircularQueue() {
front = -1;
rear = -1;
cout << "Initial state => Front: " << front << ", Rear: " << rear << endl;
bool isFull() {
return (front == 0 && rear == SIZE - 1) || (front == rear + 1);
bool isEmpty() {
return front == -1;
void enqueue(int value) {
if (isFull()) {
cout << " Queue Overflow! Cannot insert " << value << endl;
displayPointers();
return;
}
if (isEmpty()) {
front = rear = 0;
} else if (rear == SIZE - 1) {
rear = 0; // Wrap around
} else {
rear++;
Q[rear] = value;
cout << " Inserted: " << value << endl;
displayPointers();
void dequeue() {
if (isEmpty()) {
cout << " Queue Underflow! Nothing to delete.\n";
displayPointers();
return;
int deletedValue = Q[front];
if (front == rear) {
front = rear = -1; // Queue becomes empty
} else if (front == SIZE - 1) {
front = 0; // Wrap around
} else {
front++;
cout << " Deleted: " << deletedValue << endl;
displayPointers();
void display() {
if (isEmpty()) {
cout << "Queue is empty.\n";
return;
cout << "Queue elements: ";
if (rear >= front) {
for (int i = front; i <= rear; i++) {
cout << Q[i] << " ";
} else {
for (int i = front; i < SIZE; i++) {
cout << Q[i] << " ";
for (int i = 0; i <= rear; i++) {
cout << Q[i] << " ";
cout << endl;
}
void displayPointers() {
cout << "Front: " << front << ", Rear: " << rear << endl;
};
int main() {
CircularQueue q;
int choice, value;
do {
cout << "\n====== MENU ======\n";
cout << "1. Insert (enqueue)\n2. Delete (dequeue)\n3. Display Queue\n4. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter value to insert: ";
cin >> value;
q.enqueue(value);
break;
case 2:
q.dequeue();
break;
case 3:
q.display();
break;
case 4:
cout << "Exiting program.\n";
break;
default:
cout << "Invalid choice. Try again.\n";
} while (choice != 4);
return 0;
}
#include <iostream>
using namespace std;
class Deque {
private:
int front, rear;
int Q[5];
const int SIZE = 5;
public:
Deque() {
front = -1;
rear = -1;
cout << "Initial state => Front: " << front << ", Rear: " << rear << endl;
bool isFull() {
return (front == 0 && rear == SIZE - 1) || (front == rear + 1);
bool isEmpty() {
return front == -1;
void insertFront(int value) {
if (isFull()) {
cout << " Deque Overflow at Front!\n";
displayPointers();
return;
}
if (isEmpty()) {
front = rear = 0;
} else if (front == 0) {
front = SIZE - 1;
} else {
front--;
Q[front] = value;
cout << "Inserted at Front: " << value << endl;
displayPointers();
void insertRear(int value) {
if (isFull()) {
cout << " Deque Overflow at Rear!\n";
displayPointers();
return;
if (isEmpty()) {
front = rear = 0;
} else if (rear == SIZE - 1) {
rear = 0;
} else {
rear++;
}
Q[rear] = value;
cout << " Inserted at Rear: " << value << endl;
displayPointers();
void deleteFront() {
if (isEmpty()) {
cout << " Deque Underflow at Front!\n";
displayPointers();
return;
int deletedValue = Q[front];
if (front == rear) {
front = rear = -1;
} else if (front == SIZE - 1) {
front = 0;
} else {
front++;
cout << "Deleted from Front: " << deletedValue << endl;
displayPointers();
void deleteRear() {
if (isEmpty()) {
cout << " Deque Underflow at Rear!\n";
displayPointers();
return;
int deletedValue = Q[rear];
if (front == rear) {
front = rear = -1;
} else if (rear == 0) {
rear = SIZE - 1;
} else {
rear--;
cout << " Deleted from Rear: " << deletedValue << endl;
displayPointers();
void display() {
if (isEmpty()) {
cout << "Deque is empty.\n";
return;
cout << "Deque elements: ";
int i = front;
while (true) {
cout << Q[i] << " ";
if (i == rear) break;
i = (i + 1) % SIZE;
cout << endl;
void displayPointers() {
cout << "Front: " << front << ", Rear: " << rear << endl;
};
int main() {
Deque dq;
int choice, value;
do {
cout << "\n====== MENU ======\n";
cout << "1. Insert at Front\n2. Insert at Rear\n3. Delete from Front\n4. Delete from Rear\n";
cout << "5. Display Deque\n6. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter value to insert at front: ";
cin >> value;
dq.insertFront(value);
break;
case 2:
cout << "Enter value to insert at rear: ";
cin >> value;
dq.insertRear(value);
break;
case 3:
dq.deleteFront();
break;
case 4:
dq.deleteRear();
break;
case 5:
dq.display();
break;
case 6:
cout << "Exiting program.\n";
break;
default:
cout << "Invalid choice. Try again.\n";
} while (choice != 6);
return 0;
}
What Is Modulo (%)?
The modulo operator gives the remainder after division. For example:
7 % 5 = 2 because 7 divided by 5 leaves a remainder of 2.
4 % 5 = 4 because 4 is less than 5.
5 % 5 = 0 which is crucial in circular queues — it wraps around.
Circular Behavior in Queues
In a normal queue (linear), when you reach the last index of the array, you can't go further. But in
a circular queue or deque, when you hit the last index, you "wrap around" to the beginning —
just like going in a circle.
Suppose we have:
int Q[5]; // Array size = 5; indices are 0 to 4
When the rear reaches index 4 and we want to insert more (if space is available), we loop back to
index 0 using:
rear = (rear + 1) % SIZE;
Simulating the Queue
Imagine a situation where elements are inserted in a wrapped-around manner:
Q = [60, 70, 30, 40, 50]
front = 2 (value = 30)
rear = 1 (value = 70)
Although in array form they appear disjointed, logically the queue is:
30 → 40 → 50 → 60 → 70
If you try to loop from front to rear using:
for (int i = front; i <= rear; i++)
It fails, because front = 2, rear = 1 and 2 <= 1 is false.
Fixing It Using Modulo
To properly loop through a circular queue, you use:
int i = front;
while (true) {
cout << Q[i] << " ";
if (i == rear) break;
i = (i + 1) % SIZE;
}
Here's how it works step-by-step:
Start at i = 2 → Q[2] = 30
Next: (2 + 1) % 5 = 3 → Q[3] = 40
Next: (3 + 1) % 5 = 4 → Q[4] = 50
Next: (4 + 1) % 5 = 0 → Q[0] = 60
Next: (0 + 1) % 5 = 1 → Q[1] = 70
Now i == rear, so break the loop
This way, the queue prints in logical order even though physically the elements are stored across
the end and start of the array.
Why Modulo Is Crucial
The modulo operation ensures:
Indices stay within bounds (0 to SIZE - 1)
Automatic wrap-around from end to start
Logical order is maintained even with circular insertion/deletion
So, (i + 1) % SIZE is the key trick that powers circular queues and deques!